blob: d4e92b2dd01e4702cc229880d5d93b5cce431fb1 [file] [log] [blame]
/*
<:copyright-BRCM:2016:DUAL/GPL:standard
Broadcom Proprietary and Confidential.(c) 2016 Broadcom
All Rights Reserved
Unless you and Broadcom execute a separate written software license
agreement governing use of this software, this software is licensed
to you under the terms of the GNU General Public License version 2
(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
with the following added to such license:
As a special exception, the copyright holders of this software give
you permission to link this software with independent modules, and
to copy and distribute the resulting executable under terms of your
choice, provided that you also meet, for each linked independent
module, the terms and conditions of the license of that module.
An independent module is a module which is not derived from this
software. The special exception does not apply to any modifications
of the software.
Not withstanding the above, under no circumstances may you combine
this software in any way with any other Broadcom software provided
under a license other than the GPL, without Broadcom's express prior
written consent.
:>
*/
#include "bcmolt_fld.h"
#ifdef TX_ENABLE_EVENT_TRACE
#include "bcmolt_llpcie.h"
#endif
/* internal data base */
static uint32_t max_bcm68620_device = 0;
static bcm_fld_device_info *bcm68620_info = NULL;
#define SRAM_ADDRESS(device,offset) (uint32_t *)(bcm68620_info[device].soc_sram_base + offset)
bcmos_errno bcm_fld_init(uint32_t max_devices)
{
max_bcm68620_device = max_devices;
bcm68620_info = (bcm_fld_device_info *)bcmos_alloc(max_devices * sizeof(bcm_fld_device_info));
if (!bcm68620_info)
return BCM_ERR_NOMEM;
memset(bcm68620_info, 0, max_devices * sizeof(bcm_fld_device_info));
return BCM_ERR_OK;
}
void bcm_fld_clear_comm_area(uint32_t device)
{
memset((char *)SRAM_ADDRESS(device,BCM_FLD_COMMUNICATION_AREA_BASE), 0 ,BCM_FLD_COMMUNICATION_AREA_SIZE);
#if defined(TX_ENABLE_EVENT_TRACE) && defined(DEBUG_TRACE_INIT)
bcm_ll_pcie_setrace(device);
#endif
}
bcmos_errno bcm_fld_exit(void)
{
if (bcm68620_info)
bcmos_free(bcm68620_info);
bcm68620_info = NULL;
return BCM_ERR_OK;
}
/* register a device to driver
returns the driver index, instead the user's
store the user,s information about the device */
bcmos_errno bcm_fld_register(uint32_t device, bcm_fld_device_info *info)
{
if (!info)
return BCM_ERR_PARM;
if (!bcm68620_info)
return BCM_ERR_NORES;
if (device >= max_bcm68620_device)
return BCM_ERR_RANGE;
if (bcm68620_info[device].soc_sram_base)
return BCM_ERR_ALREADY;
/* copy the information received from the user to uint32_ternal data base */
bcm68620_info[device].soc_sram_base = info->soc_sram_base;
bcm68620_info[device].soc_ddr_base = info->soc_ddr_base;
bcm68620_info[device].soc_regs_base = info->soc_regs_base;
bcm68620_info[device].soc_ddr_length = info->soc_ddr_length;
return BCM_ERR_OK;
}
/* remove a device from uint32_ternal data base */
bcmos_errno bcm_fld_unregister(uint32_t device)
{
if (!bcm68620_info)
return BCM_ERR_NORES;
if (device >= max_bcm68620_device)
return BCM_ERR_RANGE;
/* clear the uint32_ternal data base for the given device */
bcm68620_info[device].soc_sram_base = 0;
bcm68620_info[device].soc_ddr_base = 0;
bcm68620_info[device].soc_ddr_length = 0;
bcm68620_info[device].soc_crt_length = 0;
bcm68620_info[device].soc_regs_base = 0;
return BCM_ERR_OK;
}
/* read from communication area and return the soc state
reset reason and protocol version */
bcmos_errno bcm_fld_get_device_status(uint32_t device, bcm_fld_device_stat *debug_state)
{
if (!debug_state)
return BCM_ERR_PARM;
if (!bcm68620_info)
return BCM_ERR_NORES;
if (device >= max_bcm68620_device)
return BCM_ERR_RANGE;
/* read from SRAM os entry offset, CPU status, reason and protocol version */
debug_state->protocol_version = bcm_pci_read32(SRAM_ADDRESS(device,BCM_FLD_BOOT_PROTOCOL_VERSION_OFFSET));
debug_state->state = bcm_pci_read32(SRAM_ADDRESS(device,BCM_FLD_CPU_STATE_OFFSET));
debug_state->reason = bcm_pci_read32(SRAM_ADDRESS(device,BCM_FLD_CPU_RESET_REASON_OFFSET));
debug_state->os_entry_offset = bcm_pci_read32(SRAM_ADDRESS(device,BCM_FLD_OS_ENTRY_OFFSET));
return BCM_ERR_OK;
}
/* returns the last soc state */
bcmos_errno bcm_fld_get_device_loading_state(uint32_t device, BCM_FLD_CPU_STATE *cpu_state)
{
uint32_t temp;
volatile uint32_t value;
if (!cpu_state)
return BCM_ERR_PARM;
if (!bcm68620_info)
return BCM_ERR_NORES;
if (device >= max_bcm68620_device)
return BCM_ERR_RANGE;
value = bcm_pci_read32(SRAM_ADDRESS(device,BCM_FLD_CPU_STATE_OFFSET));
temp = value & BCM_FLD_CPU_READY_MASK;
if (temp)
*cpu_state = BCM_FLD_CPU_READY;
else
{
temp = value & BCM_FLD_CPU_FINISH_BOOTLOADER_MASK;
if (temp)
*cpu_state = BCM_FLD_CPU_FINISH_BOOTLOADER;
else
*cpu_state = BCM_FLD_CPU_STATE_UNKNOWN;
}
return BCM_ERR_OK;
}
/* write in communication area the current host status during loading process */
bcmos_errno bcm_fld_host_finish_write_ddr(uint32_t device, uint32_t os_entry_address)
{
if (!bcm68620_info)
return BCM_ERR_NORES;
if (device >= max_bcm68620_device)
return BCM_ERR_RANGE;
/* write os_entry address of the code from DDR */
bcm_pci_write32(SRAM_ADDRESS(device,BCM_FLD_OS_ENTRY_OFFSET), os_entry_address);
/* run code from DDR */
bcm_pci_write32(SRAM_ADDRESS(device,BCM_FLD_HOST_STATE_OFFSET), BCM_FLD_HOST_FINISH_WRITE_DDR_MASK);
return BCM_ERR_OK;
}
/* return the logs area */
bcmos_errno bcm_fld_get_logs(uint32_t device, char **log_area, int *length)
{
if (!log_area || !length)
return BCM_ERR_PARM;
if (!bcm68620_info)
return BCM_ERR_NORES;
if (device >= max_bcm68620_device)
return BCM_ERR_RANGE;
*log_area = (char *)SRAM_ADDRESS(device, BCM_FLD_LOGGER_BASE);
*length = BCM_FLD_LOGGER_TOP;
return BCM_ERR_OK;
}
/* write the received buffer to memory according to offset and type */
bcmos_errno bcm_fld_write(uint32_t device, char *buff, uint32_t buff_size, uint32_t offset_in_image, bcmolt_device_image_type image_type)
{
unsigned long address = 0;
int i;
#ifndef PCIE_BYTE_COPY
uint32_t size, rest;
uint32_t* buff_32;
uint32_t* addr_32;
#endif
if (!buff)
return BCM_ERR_PARM;
if (!bcm68620_info)
return BCM_ERR_NORES;
if (device >= max_bcm68620_device)
return BCM_ERR_RANGE;
if (image_type == BCMOLT_DEVICE_IMAGE_TYPE_BOOTLOADER)
{
address = bcm68620_info[device].soc_sram_base + offset_in_image;
if ((offset_in_image + buff_size) > BCM_FLD_COMMUNICATION_AREA_BASE)
return BCM_ERR_OVERFLOW;
}
else if (image_type == BCMOLT_DEVICE_IMAGE_TYPE_APPLICATION)
{
address = bcm68620_info[device].soc_ddr_base + offset_in_image;
if ((offset_in_image + buff_size) > bcm68620_info[device].soc_ddr_length)
return BCM_ERR_OVERFLOW;
bcm68620_info[device].soc_crt_length += buff_size;
}
else
{
return BCM_ERR_PARM;
}
#ifndef PCIE_BYTE_COPY
size = buff_size / sizeof(*buff_32);
rest = buff_size & (sizeof(*buff_32) -1);
buff_32 = (uint32_t*)buff;
addr_32 = (uint32_t*)address;
if (rest)
size++;
for(i = 0; i < size; i++)
bcm_pci_write32((addr_32 + i),BCMOS_ENDIAN_CPU_TO_LITTLE_U32(*(buff_32 +i)));
#else
for (i = 0; i < buff_size; i++)
*(uint8_t *)(address + i) = buff[i];
#endif
bcmos_barrier();
return BCM_ERR_OK;
}
/* read to the received buffer from memory according to offset and type */
bcmos_errno bcm_fld_read(uint32_t device, char *buff, uint32_t *buff_size, uint32_t offset_in_image, bcmolt_device_image_type image_type)
{
unsigned long address = 0;
uint32_t i;
#ifndef PCIE_BYTE_COPY
uint32_t size, rest;
uint32_t* buff_32;
uint32_t* addr_32;
#endif
if (!buff || !buff_size)
return BCM_ERR_PARM;
if (!bcm68620_info)
return BCM_ERR_NORES;
if (device >= max_bcm68620_device)
return BCM_ERR_RANGE;
if(image_type == BCMOLT_DEVICE_IMAGE_TYPE_BOOTLOADER)
address = bcm68620_info[device].soc_sram_base + offset_in_image;
else if (image_type == BCMOLT_DEVICE_IMAGE_TYPE_APPLICATION)
address = bcm68620_info[device].soc_ddr_base + offset_in_image;
else
return BCM_ERR_PARM;
/* temporary for test , consider to integrate in future */
#ifndef PCIE_BYTE_COPY
size = *buff_size /sizeof(*buff_32);
rest = *buff_size & (sizeof(*buff_32) -1);
buff_32 = (uint32_t*)buff;
addr_32 = (uint32_t*)address;
if (rest)
size++;
for(i = 0; i < size; i++)
*(buff_32 +i)= BCMOS_ENDIAN_CPU_TO_LITTLE_U32(bcm_pci_read32((uint32_t *)(addr_32 + i)));
#else
for (i = 0; i < *buff_size; i++)
buff[i] = *(uint8_t *)(address + i);
#endif
bcmos_barrier();
return BCM_ERR_OK;
}
/*********** PMC definitions ****************/
#define PMC_QUEUE_0_DATA_UNRESET0 0x401c00U
#define PMC_QUEUE_0_DATA_UNRESET1 0x401c04U
#define PMC_QUEUE_0_DATA_UNRESET2 0x401c08U
#define PMC_QUEUE_0_DATA_UNRESET3 0x401c0cU
#define PMC_QUEUE_1_DATA_UNRESET0 0x401c10U
#define PMC_QUEUE_1_DATA_UNRESET1 0x401c14U
#define PMC_QUEUE_1_DATA_UNRESET2 0x401c18U
#define PMC_QUEUE_1_DATA_UNRESET3 0x401c1cU
#define PMC_CNTRL_HOST_MBOX_IN 0x401028U
#define PMC_HOST_MBOX_MASK 0x2
#define PMC_PMB_CNTRL 0x4800c0U
/* The below value is the swap of ((1 << 31) | (1<<20) | (4 << 12) | (0x0C)) */
#define PMC_PMB_CMD 0x0C401080
#define PMC_PMB_WRITE 0x4800c4U
/* The below value is the swap of 0x1*/
#define PMC_PMB_ADDRESS 0x1000000
/* PMC command to take ARM out of reset */
#define ARM_OUT_OF_RESET 35
/********************************************/
bcmos_errno bcm_fld_start_bootloader(uint32_t device, uint32_t test_ddr)
{
/* temporary disabled: just for A0, should be enabled in B0
#ifdef BCM_PMC_EXIST
volatile uint32_t readval;
#endif
*/
if (!bcm68620_info)
return BCM_ERR_NORES;
if (device >= max_bcm68620_device)
return BCM_ERR_RANGE;
bcm_pci_write32(SRAM_ADDRESS(device, BCM_FLD_HOST_STATE_OFFSET), test_ddr);
/* start processor */
bcm_fld_set_host_debug_status(device, BCM_FLD_HOST_START_CPU);
/* Temporary disabled - should be enabled in B0
#ifndef BCM_PMC_EXIST */
bcm_pci_read32((uint32_t *)(bcm68620_info[device].soc_regs_base + PMC_PMB_CNTRL));
bcm_pci_write32((uint32_t *)(bcm68620_info[device].soc_regs_base + PMC_PMB_WRITE), PMC_PMB_ADDRESS);
bcm_pci_read32((uint32_t *)(bcm68620_info[device].soc_regs_base + PMC_PMB_WRITE));
bcm_pci_write32((uint32_t *)(bcm68620_info[device].soc_regs_base + PMC_PMB_CNTRL), PMC_PMB_CMD);
bcm_pci_read32((uint32_t *)(bcm68620_info[device].soc_regs_base + PMC_PMB_CNTRL));
/*
#else
readval = bcm_pci_read32((uint32_t *)(bcm68620_info[device].soc_regs_base + PMC_CNTRL_HOST_MBOX_IN));
if (!(readval & PMC_HOST_MBOX_MASK))
return BCM_ERR_NOT_CONNECTED;
bcm_pci_write32((bcm68620_info[device].soc_regs_base + PMC_QUEUE_0_DATA_UNRESET0), BCMOS_ENDIAN_CPU_TO_LITTLE_U32(ARM_OUT_OF_RESET));
bcm_pci_write32((bcm68620_info[device].soc_regs_base + PMC_QUEUE_0_DATA_UNRESET1), BCMOS_ENDIAN_CPU_TO_LITTLE_U32(0));
bcm_pci_write32((bcm68620_info[device].soc_regs_base + PMC_QUEUE_0_DATA_UNRESET2), BCMOS_ENDIAN_CPU_TO_LITTLE_U32(0));
bcm_pci_write32((bcm68620_info[device].soc_regs_base + PMC_QUEUE_0_DATA_UNRESET3), BCMOS_ENDIAN_CPU_TO_LITTLE_U32(0));
bcmos_usleep(10000); // 10 msec
// read PMC response, to clean the queue
bcm_pci_read32((uint32_t *)(bcm68620_info[device].soc_regs_base + PMC_QUEUE_1_DATA_UNRESET0));
bcm_pci_read32((uint32_t *)(bcm68620_info[device].soc_regs_base + PMC_QUEUE_1_DATA_UNRESET1));
bcm_pci_read32((uint32_t *)(bcm68620_info[device].soc_regs_base + PMC_QUEUE_1_DATA_UNRESET2));
bcm_pci_read32((uint32_t *)(bcm68620_info[device].soc_regs_base + PMC_QUEUE_1_DATA_UNRESET3));
#endif
*/
return BCM_ERR_OK;
}
bcmos_bool bcm_fld_is_bootloader_done(uint32_t device)
{
volatile uint32_t value;
if (!bcm68620_info)
return BCMOS_FALSE;
if (device >= max_bcm68620_device)
return BCMOS_FALSE;
value = bcm_pci_read32(SRAM_ADDRESS(device,BCM_FLD_CPU_STATE_OFFSET));
if (value & BCM_FLD_CPU_FINISH_BOOTLOADER_MASK)
return BCMOS_TRUE;
return BCMOS_FALSE;
}
bcmos_bool bcm_fld_is_ddr_test_done(uint32_t device)
{
uint32_t value = bcm_pci_read32(SRAM_ADDRESS(device, BCM_FLD_CPU_STATE_OFFSET));
return 0 != (value & BCM_FLD_DDR_TEST_DONE_MASK);
}
bcmos_bool bcm_fld_test_device_bootrecord_flag(uint32_t device)
{
volatile uint32_t value;
if (!bcm68620_info)
return BCMOS_FALSE;
if (device >= max_bcm68620_device)
return BCMOS_FALSE;
value = bcm_pci_read32(SRAM_ADDRESS(device,BCM_FLD_CPU_BOOTREC_STATE_OFFSET));
if (value & BCM_FLD_CPU_PRM_VALID_MASK)
return BCMOS_TRUE;
return BCMOS_FALSE;
}
bcmos_errno bcm_fld_get_device_bootrecord(uint32_t device, uint32_t *opaque_data)
{
uint32_t *addr, *temp;
int32_t i;
if (!opaque_data)
return BCM_ERR_PARM;
if (!bcm68620_info)
return BCM_ERR_NORES;
if (device >= max_bcm68620_device)
return BCM_ERR_RANGE;
temp = opaque_data;
addr = SRAM_ADDRESS(device,BCM_FLD_CPU_BOOTRECORD_OFFSET);
for (i = 0; i < PCIE_OPAQUE_DATA_SIZE / 4; i++)
{
*temp++ = bcm_pci_read32(addr++);
}
return BCM_ERR_OK;
}
bcmos_errno bcm_fld_clear_device_bootrecord_flag(uint32_t device)
{
volatile uint32_t value;
if (!bcm68620_info)
return BCM_ERR_NORES;
if (device >= max_bcm68620_device)
return BCM_ERR_RANGE;
/* clear SoC prm valid bit */
value = bcm_pci_read32(SRAM_ADDRESS(device,BCM_FLD_CPU_BOOTREC_STATE_OFFSET));
value &= ~BCM_FLD_CPU_PRM_VALID_MASK;
bcm_pci_write32(SRAM_ADDRESS(device,BCM_FLD_CPU_BOOTREC_STATE_OFFSET), value);
return BCM_ERR_OK;
}
bcmos_errno bcm_fld_set_host_bootrecord_flag(uint32_t device)
{
volatile uint32_t value;
if (!bcm68620_info)
return BCM_ERR_NORES;
if (device >= max_bcm68620_device)
return BCM_ERR_RANGE;
/* set host prm valid bit */
value = bcm_pci_read32(SRAM_ADDRESS(device,BCM_FLD_HOST_BOOTREC_STATE_OFFSET));
value |= ((1 << BCM_FLD_HOST_PRM_VALID_SHIFT) & BCM_FLD_HOST_PRM_VALID_MASK);
bcm_pci_write32(SRAM_ADDRESS(device,BCM_FLD_HOST_BOOTREC_STATE_OFFSET), value);
return BCM_ERR_OK;
}
bcmos_bool bcm_fld_test_host_bootrecord_flag(uint32_t device)
{
volatile uint32_t value;
if (!bcm68620_info)
return BCMOS_FALSE;
if (device >= max_bcm68620_device)
return BCMOS_FALSE;
value = bcm_pci_read32(SRAM_ADDRESS(device,BCM_FLD_HOST_BOOTREC_STATE_OFFSET));
if (value & BCM_FLD_HOST_PRM_VALID_MASK)
return BCMOS_TRUE;
return BCMOS_FALSE;
}
bcmos_errno bcm_fld_set_rings_size(uint32_t device, uint32_t host_tx_size, uint32_t host_rx_size)
{
volatile uint32_t value;
if (!bcm68620_info)
return BCM_ERR_NORES;
if (device >= max_bcm68620_device)
return BCM_ERR_RANGE;
/* write host_pd_ring_size to communication area - SoC will use it in first stages of application */
/* device tx ring size is the same as host rx queue */
bcm_pci_write32(SRAM_ADDRESS(device,BCM_FLD_HOST_RX_QUEUE_SIZE_OFFSET), host_rx_size);
/* device rx ring size is the same as host tx queue */
bcm_pci_write32(SRAM_ADDRESS(device,BCM_FLD_CPU_RX_QUEUE_SIZE_OFFSET), host_tx_size);
/* set host queue valid bit */
value = bcm_pci_read32(SRAM_ADDRESS(device,BCM_FLD_CPU_SET_QUEUES_SIZE));
value |= ((1 << BCM_FLD_CPU_QUEUE_VALID_SHIFT) & BCM_FLD_CPU_QUEUE_VALID_MASK);
bcm_pci_write32(SRAM_ADDRESS(device,BCM_FLD_CPU_SET_QUEUES_SIZE), value);
return BCM_ERR_OK;
}
bcmos_errno bcm_fld_get_exception_state(uint32_t device, uint32_t *state0, uint32_t *state1)
{
if (!bcm68620_info)
return BCM_ERR_NORES;
if (device >= max_bcm68620_device)
return BCM_ERR_RANGE;
if (!state0 || !state1)
return BCM_ERR_PARM;
*state0 = bcm_pci_read32(SRAM_ADDRESS(device, BCM_FLD_CPU0_POSTMORTEM_STATE));
*state1 = bcm_pci_read32(SRAM_ADDRESS(device, BCM_FLD_CPU1_POSTMORTEM_STATE));
return BCM_ERR_OK;
}
bcmos_errno bcm_fld_clear_exception_state(uint32_t device, uint32_t cpuid)
{
uint32_t offset = cpuid ? BCM_FLD_CPU1_POSTMORTEM_STATE : BCM_FLD_CPU0_POSTMORTEM_STATE;
if (!bcm68620_info)
return BCM_ERR_NORES;
if ((device >= max_bcm68620_device) || (cpuid > 1))
return BCM_ERR_RANGE;
bcm_pci_write32(SRAM_ADDRESS(device, offset), 0);
return BCM_ERR_OK;
}
bcmos_errno bcm_fld_copy_exception_log(uint32_t device, uint32_t cpuid, char *buffer, int *length)
{
BCM_FLD_POSTMORTEM_LOG *exlog;
uint32_t offset = cpuid ? BCM_FLD_CPU1_POSTMORTEM_BUF_OFFSET : BCM_FLD_CPU0_POSTMORTEM_BUF_OFFSET;
if (!bcm68620_info)
return BCM_ERR_NORES;
if ((device >= max_bcm68620_device) || (cpuid > 1))
return BCM_ERR_RANGE;
if (!buffer || !length)
return BCM_ERR_PARM;
exlog = (BCM_FLD_POSTMORTEM_LOG *)SRAM_ADDRESS(device, offset);
if (exlog->magic != BCM_FLD_POSTMORTEM_LOG_MAGIC)
*length = 0;
else
{
int i;
*length = exlog->msg_len;
/* if host is 64 bit and bigendian memcpy does not work correctly */
for (i=0; i < exlog->msg_len; i++)
{
buffer[i] = exlog->msg[i];
}
}
buffer[*length] = '\0';
return BCM_ERR_OK;
}
/**
* \Debug states and functions
*/
bcmos_errno bcm_fld_get_device_debug_status(uint32_t device, bcm_fld_device_debug_state *info)
{
volatile uint32_t value;
if (!info)
return BCM_ERR_PARM;
if (!bcm68620_info)
return BCM_ERR_NORES;
if (device >= max_bcm68620_device)
return BCM_ERR_RANGE;
value = bcm_pci_read32(SRAM_ADDRESS(device,BCM_FLD_CPU_DEBUG_STATE_OFFSET));
info->boot_from_sram_states = (value & BCM_FLD_CPU_BOOT_FROM_SRAM_STATES_MASK) >> BCM_FLD_CPU_BOOT_FROM_SRAM_STATES_SHIFT;
info->boot_from_sram_errors = (value & BCM_FLD_CPU_BOOT_FROM_SRAM_ERRORS_MASK) >> BCM_FLD_CPU_BOOT_FROM_SRAM_ERRORS_SHIFT;
info->boot_from_sram_exception = (value & BCM_FLD_CPU_BOOT_FROM_SRAM_EXCEPTION_MASK) >> BCM_FLD_CPU_BOOT_FROM_SRAM_EXCEPTION_SHIFT;
info->run_from_ddr_state = (value & BCM_FLD_CPU_RUN_FROM_DDR_STATES_MASK) >> BCM_FLD_CPU_RUN_FROM_DDR_STATES_SHIFT;
return BCM_ERR_OK;
}
bcmos_errno bcm_fld_get_host_debug_status(uint32_t device, bcm_fld_host_debug_state *info)
{
volatile uint32_t value;
if (!info)
return BCM_ERR_PARM;
if (!bcm68620_info)
return BCM_ERR_NORES;
if (device >= max_bcm68620_device)
return BCM_ERR_RANGE;
value = bcm_pci_read32(SRAM_ADDRESS(device,BCM_FLD_HOST_DEBUG_STATE_OFFSET));
info->write_sram = (value & BCM_FLD_HOST_WRITE_SRAM_MASK) >> BCM_FLD_HOST_WRITE_SRAM_SHIFT;
info->start_device = (value & BCM_FLD_HOST_START_CPU_MASK) >> BCM_FLD_HOST_START_CPU_SHIFT;
info->write_ddr = (value & BCM_FLD_HOST_WRITE_DDR_MASK) >> BCM_FLD_HOST_WRITE_DDR_SHIFT;
value = bcm_pci_read32(SRAM_ADDRESS(device,BCM_FLD_HOST_STATE_OFFSET));
info->finish_ddr = (value & BCM_FLD_HOST_FINISH_WRITE_DDR_MASK) >> BCM_FLD_HOST_FINISH_WRITE_DDR_SHIFT;
return BCM_ERR_OK;
}
bcmos_errno bcm_fld_set_host_debug_status(uint32_t device, BCM_FLD_HOST_DEBUG_VALUES stat)
{
volatile uint32_t value = 0;
if (!bcm68620_info)
return BCM_ERR_NORES;
if (device >= max_bcm68620_device)
return BCM_ERR_RANGE;
if (stat == BCM_FLD_HOST_WRITE_SRAM)
value = ((1 << BCM_FLD_HOST_WRITE_SRAM_SHIFT) & BCM_FLD_HOST_WRITE_SRAM_MASK);
else
{
value = bcm_pci_read32(SRAM_ADDRESS(device,BCM_FLD_HOST_DEBUG_STATE_OFFSET));
if (stat == BCM_FLD_HOST_START_CPU)
value |= ((1 << BCM_FLD_HOST_START_CPU_SHIFT) & BCM_FLD_HOST_START_CPU_MASK);
else if (stat == BCM_FLD_HOST_WRITE_DDR)
value |= ((1 << BCM_FLD_HOST_WRITE_DDR_SHIFT) & BCM_FLD_HOST_WRITE_DDR_MASK);
else
return BCM_ERR_PARM;
}
bcm_pci_write32(SRAM_ADDRESS(device,BCM_FLD_HOST_DEBUG_STATE_OFFSET), value);
return BCM_ERR_OK;
}
bcmos_errno bcm_fld_set_ras_mode_set(uint32_t device, uint32_t ras, uint32_t mode)
{
uint32_t offset = ras ? BCM_FLD_RAS_1_SETTINGS :BCM_FLD_RAS_0_SETTINGS;
bcm_pci_write32(SRAM_ADDRESS(device, offset), mode);
return BCM_ERR_OK;
}
bcmos_errno bcm_fld_set_host_event(uint32_t device, uint32_t event)
{
if (!bcm68620_info)
return BCM_ERR_NORES;
if (device >= max_bcm68620_device)
return BCM_ERR_RANGE;
bcm_pci_write32(SRAM_ADDRESS(device, BCM_FLD_HOST_EVENT), event);
return BCM_ERR_OK;
}
bcmos_bool bcm_fld_test_queues_flag(uint32_t device)
{
volatile uint32_t value;
if (!bcm68620_info)
return BCMOS_FALSE;
if (device >= max_bcm68620_device)
return BCMOS_FALSE;
value = bcm_pci_read32(SRAM_ADDRESS(device,BCM_FLD_CPU_SET_QUEUES_SIZE));
if (value & BCM_FLD_CPU_QUEUE_VALID_MASK)
return BCMOS_TRUE;
return BCMOS_FALSE;
}
bcmos_bool bcm_fld_regs_swap_needed(uint32_t device)
{
uint32_t value;
value = *(volatile uint32_t *)(bcm68620_info[device].soc_regs_base + PCIE_REVISION_REGISTER_OFFSET);
if ((value & 0xffff) != 0x0302)
return BCMOS_TRUE;
return BCMOS_FALSE;
}
bcmos_bool bcm_fld_sram_swap_needed(uint32_t device)
{
uint32_t value;
uint8_t charvalue;
value = 0xaabbccdd;
*(volatile uint32_t *)bcm68620_info[device].soc_sram_base = value;
charvalue = *(volatile uint8_t *)bcm68620_info[device].soc_sram_base;
if (charvalue != *(uint8_t *)&value)
return BCMOS_TRUE;
return BCMOS_FALSE;
}
bcmos_bool bcm_fld_ddr_swap_needed(uint32_t device)
{
uint32_t value;
volatile uint32_t *address;
uint8_t charvalue;
value = 0xaabbccdd;
address = (uint32_t *)(bcm68620_info[device].soc_ddr_base + bcm68620_info[device].soc_crt_length);
*address = value;
charvalue = *address;
if (charvalue != *&value)
return BCMOS_TRUE;
return BCMOS_FALSE;
}
#ifdef TX_ENABLE_EVENT_TRACE
bcmos_errno bcm_fld_set_event_trace(uint32_t device)
{
if (!bcm68620_info)
return BCM_ERR_NORES;
if (device >= max_bcm68620_device)
return BCM_ERR_RANGE;
bcm_pci_write32(SRAM_ADDRESS(device,BCM_FLD_EVENT_TRACE_OFFSET), 0x1);
return BCM_ERR_OK;
}
bcmos_errno bcm_fld_clear_event_trace(uint32_t device)
{
if (!bcm68620_info)
return BCM_ERR_NORES;
if (device >= max_bcm68620_device)
return BCM_ERR_RANGE;
bcm_pci_write32(SRAM_ADDRESS(device,BCM_FLD_EVENT_TRACE_OFFSET), 0x0);
return BCM_ERR_OK;
}
#endif
#ifdef DMA_STUB
bcmos_errno bcm_fld_set_device_bootrecord_flag(uint32_t device)
{
volatile uint32_t value;
value = BCM_FLD_CPU_PRM_VALID_MASK;
bcm_pci_write32(SRAM_ADDRESS(device,BCM_FLD_CPU_BOOTREC_STATE_OFFSET), value);
return BCM_ERR_OK;
}
bcmos_errno bcm_fld_set_device_bootrecord(uint32_t device, uint32_t *opaque_data)
{
uint32_t *addr, *temp;
int32_t i;
temp = opaque_data;
addr = SRAM_ADDRESS(device,BCM_FLD_CPU_BOOTRECORD_OFFSET);
for (i = 0; i < PCIE_OPAQUE_DATA_SIZE / 4; i++)
{
bcm_pci_write32(addr++,*temp++);
}
return BCM_ERR_OK;
}
#endif
bcmos_errno bcm_fld_set_avs_cont(uint32_t device, uint32_t value)
{
bcm_pci_write32(SRAM_ADDRESS(device, BCM_FLD_AVS_SETTINGS), value);
return BCM_ERR_OK;
}
void *bcm_fld_get_sw_error_table(uint32_t device, uint32_t *size)
{
*size = BCM_FLD_SW_ERROR_TABLE_SIZE;
return SRAM_ADDRESS(device, BCM_FLD_SW_ERROR_TABLE);
}
uint32_t bcm_fld_ddr_test_result_get(uint32_t device, uint32_t word)
{
return bcm_pci_read32(SRAM_ADDRESS(device, BCM_FLD_DDR_TEST_RESULTS + (word * COMM_WORD_SIZE)));
}
#ifdef __KERNEL__
EXPORT_SYMBOL(bcm_fld_init);
EXPORT_SYMBOL(bcm_fld_clear_comm_area);
EXPORT_SYMBOL(bcm_fld_exit);
EXPORT_SYMBOL(bcm_fld_register);
EXPORT_SYMBOL(bcm_fld_unregister);
EXPORT_SYMBOL(bcm_fld_get_device_status);
EXPORT_SYMBOL(bcm_fld_get_device_loading_state);
EXPORT_SYMBOL(bcm_fld_host_finish_write_ddr);
EXPORT_SYMBOL(bcm_fld_get_logs);
EXPORT_SYMBOL(bcm_fld_write);
EXPORT_SYMBOL(bcm_fld_read);
EXPORT_SYMBOL(bcm_fld_start_bootloader);
EXPORT_SYMBOL(bcm_fld_is_bootloader_done);
EXPORT_SYMBOL(bcm_fld_set_rings_size);
EXPORT_SYMBOL(bcm_fld_get_device_bootrecord);
EXPORT_SYMBOL(bcm_fld_test_device_bootrecord_flag);
EXPORT_SYMBOL(bcm_fld_clear_device_bootrecord_flag);
EXPORT_SYMBOL(bcm_fld_set_host_bootrecord_flag);
EXPORT_SYMBOL(bcm_fld_test_host_bootrecord_flag);
EXPORT_SYMBOL(bcm_fld_test_queues_flag);
EXPORT_SYMBOL(bcm_fld_get_device_debug_status);
EXPORT_SYMBOL(bcm_fld_get_host_debug_status);
EXPORT_SYMBOL(bcm_fld_set_host_debug_status);
EXPORT_SYMBOL(bcm_fld_set_ras_mode_set);
EXPORT_SYMBOL(bcm_fld_set_host_event);
EXPORT_SYMBOL(bcm_fld_get_exception_state);
EXPORT_SYMBOL(bcm_fld_clear_exception_state);
EXPORT_SYMBOL(bcm_fld_copy_exception_log);
EXPORT_SYMBOL(bcm_fld_regs_swap_needed);
EXPORT_SYMBOL(bcm_fld_sram_swap_needed);
EXPORT_SYMBOL(bcm_fld_ddr_swap_needed);
#ifdef TX_ENABLE_EVENT_TRACE
EXPORT_SYMBOL(bcm_fld_set_event_trace);
EXPORT_SYMBOL(bcm_fld_clear_event_trace);
#endif
EXPORT_SYMBOL(bcm_fld_set_avs_cont);
EXPORT_SYMBOL(bcm_fld_get_sw_error_table);
#endif