/* bnx2x_init_ops.h: Broadcom Everest network driver.
* Static functions needed during the initialization.
* This file is "included" in bnx2x_main.c.
*
* Copyright (c) 2007-2013 Broadcom Corporation
*
* 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.
*
* Maintained by: Eilon Greenstein <eilong@broadcom.com>
* Written by: Vladislav Zolotarov <vladz@broadcom.com>
*/
#ifndef BNX2X_INIT_OPS_H
#define BNX2X_INIT_OPS_H
#ifndef BP_ILT
#define BP_ILT(bp) NULL
#endif
#ifndef BP_FUNC
#define BP_FUNC(bp) 0
#endif
#ifndef BP_PORT
#define BP_PORT(bp) 0
#endif
#ifndef BNX2X_ILT_FREE
#define BNX2X_ILT_FREE(x, y, sz)
#endif
#ifndef BNX2X_ILT_ZALLOC
#define BNX2X_ILT_ZALLOC(x, y, sz)
#endif
#ifndef ILOG2
#define ILOG2(x) x
#endif
static int bnx2x_gunzip(struct bnx2x *bp, const u8 *zbuf, int len);
static void bnx2x_reg_wr_ind(struct bnx2x *bp, u32 addr, u32 val);
static void bnx2x_write_dmae_phys_len(struct bnx2x *bp,
dma_addr_t phys_addr, u32 addr,
u32 len);
static void bnx2x_init_str_wr(struct bnx2x *bp, u32 addr,
const u32 *data, u32 len)
{
u32 i;
for (i = 0; i < len; i++)
REG_WR(bp, addr + i*4, data[i]);
}
static void bnx2x_init_ind_wr(struct bnx2x *bp, u32 addr,
const u32 *data, u32 len)
{
u32 i;
for (i = 0; i < len; i++)
bnx2x_reg_wr_ind(bp, addr + i*4, data[i]);
}
static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len,
u8 wb)
{
if (bp->dmae_ready)
bnx2x_write_dmae_phys_len(bp, GUNZIP_PHYS(bp), addr, len);
/* in E1 chips BIOS initiated ZLR may interrupt widebus writes */
else if (wb && CHIP_IS_E1(bp))
bnx2x_init_ind_wr(bp, addr, GUNZIP_BUF(bp), len);
/* in later chips PXP root complex handles BIOS ZLR w/o interrupting */
else
bnx2x_init_str_wr(bp, addr, GUNZIP_BUF(bp), len);
}
static void bnx2x_init_fill(struct bnx2x *bp, u32 addr, int fill,
u32 len, u8 wb)
{
u32 buf_len = (((len*4) > FW_BUF_SIZE) ? FW_BUF_SIZE : (len*4));
u32 buf_len32 = buf_len/4;
u32 i;
memset(GUNZIP_BUF(bp), (u8)fill, buf_len);
for (i = 0; i < len; i += buf_len32) {
u32 cur_len = min(buf_len32, len - i);
bnx2x_write_big_buf(bp, addr + i*4, cur_len, wb);
}
}
static void bnx2x_write_big_buf_wb(struct bnx2x *bp, u32 addr, u32 len)
{
if (bp->dmae_ready)
bnx2x_write_dmae_phys_len(bp, GUNZIP_PHYS(bp), addr, len);
/* in E1 chips BIOS initiated ZLR may interrupt widebus writes */
else if (CHIP_IS_E1(bp))
bnx2x_init_ind_wr(bp, addr, GUNZIP_BUF(bp), len);
/* in later chips PXP root complex handles BIOS ZLR w/o interrupting */
else
bnx2x_init_str_wr(bp, addr, GUNZIP_BUF(bp), len);
}
static void bnx2x_init_wr_64(struct bnx2x *bp, u32 addr,
const u32 *data, u32 len64)
{
u32 buf_len32 = FW_BUF_SIZE/4;
u32 len = len64*2;
u64 data64 = 0;
u32 i;
/* 64 bit value is in a blob: first low DWORD, then high DWORD */
data64 = HILO_U64((*(data + 1)), (*data));
len64 = min((u32)(FW_BUF_SIZE/8), len64);
for (i = 0; i < len64; i++) {
u64 *pdata = ((u64 *)(GUNZIP_BUF(bp))) + i;
*pdata = data64;
}
for (i = 0; i < len; i += buf_len32) {
u32 cur_len = min(buf_len32, len - i);
bnx2x_write_big_buf_wb(bp, addr + i*4, cur_len);
}
}
/*********************************************************
There are different blobs for each PRAM section.
In addition, each blob write operation is divided into a few operations
in order to decrease the amount of phys. contiguous buffer needed.
Thus, when we select a blob the address may be with some offset
from the beginning of PRAM section.
The same holds for the INT_TABLE sections.
**********************************************************/
#define IF_IS_INT_TABLE_ADDR(base, addr) \
if (((base) <= (addr)) && ((base) + 0x400 >= (addr)))
#define IF_IS_PRAM_ADDR(base, addr) \
if (((base) <= (addr)) && ((base) + 0x40000 >= (addr)))
static const u8 *bnx2x_sel_blob(struct bnx2x *bp, u32 addr,
const u8