408 lines
16 KiB
C
408 lines
16 KiB
C
/*****************************************************************************
|
|
|
|
(c) Cambridge Silicon Radio Limited 2011
|
|
All rights reserved and confidential information of CSR
|
|
|
|
Refer to LICENSE.txt included with this source for details
|
|
on the license terms.
|
|
|
|
*****************************************************************************/
|
|
|
|
#ifndef CSR_WIFI_HIP_CHIPHELPER_H__
|
|
#define CSR_WIFI_HIP_CHIPHELPER_H__
|
|
|
|
|
|
#include <linux/types.h>
|
|
|
|
/* The age of the BlueCore chip. This is probably not useful, if
|
|
you know the age then you can probably work out the version directly. */
|
|
enum chip_helper_bluecore_age
|
|
{
|
|
chip_helper_bluecore_pre_bc7,
|
|
chip_helper_bluecore_bc7_or_later
|
|
};
|
|
|
|
/* We support up to three windowed regions at the moment.
|
|
Don't reorder these - they're used to index into an array. */
|
|
enum chip_helper_window_index
|
|
{
|
|
CHIP_HELPER_WINDOW_1 = 0,
|
|
CHIP_HELPER_WINDOW_2 = 1,
|
|
CHIP_HELPER_WINDOW_3 = 2,
|
|
CHIP_HELPER_WINDOW_COUNT = 3
|
|
};
|
|
|
|
/* These are the things that we can access through a window.
|
|
Don't reorder these - they're used to index into an array. */
|
|
enum chip_helper_window_type
|
|
{
|
|
CHIP_HELPER_WT_CODE_RAM = 0,
|
|
CHIP_HELPER_WT_FLASH = 1,
|
|
CHIP_HELPER_WT_EXT_SRAM = 2,
|
|
CHIP_HELPER_WT_ROM = 3,
|
|
CHIP_HELPER_WT_SHARED = 4,
|
|
CHIP_HELPER_WT_COUNT = 5
|
|
};
|
|
|
|
/* Commands to stop and start the XAP */
|
|
enum chip_helper_dbg_emu_cmd_enum
|
|
{
|
|
CHIP_HELPER_DBG_EMU_CMD_XAP_STEP_MASK = 0x0001,
|
|
CHIP_HELPER_DBG_EMU_CMD_XAP_RUN_B_MASK = 0x0002,
|
|
CHIP_HELPER_DBG_EMU_CMD_XAP_BRK_MASK = 0x0004,
|
|
CHIP_HELPER_DBG_EMU_CMD_XAP_WAKEUP_MASK = 0x0008
|
|
};
|
|
|
|
/* Bitmasks for Stop and sleep status: DBG_SPI_STOP_STATUS & DBG_HOST_STOP_STATUS */
|
|
enum chip_helper_dbg_stop_status_enum
|
|
{
|
|
CHIP_HELPER_DBG_STOP_STATUS_NONE_MASK = 0x0000,
|
|
CHIP_HELPER_DBG_STOP_STATUS_P0_MASK = 0x0001,
|
|
CHIP_HELPER_DBG_STOP_STATUS_P1_MASK = 0x0002,
|
|
CHIP_HELPER_DBG_STOP_STATUS_P2_MASK = 0x0004,
|
|
CHIP_HELPER_DBG_STOP_STATUS_SLEEP_STATUS_P0_MASK = 0x0008,
|
|
CHIP_HELPER_DBG_STOP_STATUS_SLEEP_STATUS_P1_MASK = 0x0010,
|
|
CHIP_HELPER_DBG_STOP_STATUS_SLEEP_STATUS_P2_MASK = 0x0020,
|
|
/* Legacy names/alias */
|
|
CHIP_HELPER_DBG_STOP_STATUS_MAC_MASK = 0x0001,
|
|
CHIP_HELPER_DBG_STOP_STATUS_PHY_MASK = 0x0002,
|
|
CHIP_HELPER_DBG_STOP_STATUS_BT_MASK = 0x0004,
|
|
CHIP_HELPER_DBG_STOP_STATUS_SLEEP_STATUS_MAC_MASK = 0x0008,
|
|
CHIP_HELPER_DBG_STOP_STATUS_SLEEP_STATUS_PHY_MASK = 0x0010,
|
|
CHIP_HELPER_DBG_STOP_STATUS_SLEEP_STATUS_BT_MASK = 0x0020
|
|
};
|
|
|
|
/* Codes to disable the watchdog */
|
|
enum chip_helper_watchdog_disable_enum
|
|
{
|
|
CHIP_HELPER_WATCHDOG_DISABLE_CODE1 = 0x6734,
|
|
CHIP_HELPER_WATCHDOG_DISABLE_CODE2 = 0xD6BF,
|
|
CHIP_HELPER_WATCHDOG_DISABLE_CODE3 = 0xC31E
|
|
};
|
|
|
|
/* Other bits have changed between versions */
|
|
enum chip_helper_gbl_misc_enum
|
|
{
|
|
CHIP_HELPER_GBL_MISC_SPI_STOP_OUT_EN_MASK = 0x0001,
|
|
CHIP_HELPER_GBL_MISC_MMU_INIT_DONE_MASK = 0x0004
|
|
};
|
|
|
|
/* Coex status register, contains interrupt status and reset pullup status.
|
|
* CHIP_HELPER_COEX_STATUS_RST_PULLS_MSB_MASK can be used to check
|
|
* for WAPI on R03 chips and later. */
|
|
enum chip_helper_coex_status_mask_enum
|
|
{
|
|
CHIP_HELPER_COEX_STATUS_RST_PULLS_LSB_MASK = 0x0001,
|
|
CHIP_HELPER_COEX_STATUS_RST_PULLS_MSB_MASK = 0x0008,
|
|
CHIP_HELPER_COEX_STATUS_WL_FEC_PINS_LSB_MASK = 0x0010,
|
|
CHIP_HELPER_COEX_STATUS_WL_FEC_PINS_MSB_MASK = 0x0080,
|
|
CHIP_HELPER_COEX_STATUS_INT_UART_MASK = 0x0100,
|
|
CHIP_HELPER_COEX_STATUS_INT_BT_LEG_MASK = 0x0200
|
|
};
|
|
|
|
/* How to select the different CPUs */
|
|
enum chip_helper_dbg_proc_sel_enum
|
|
{
|
|
CHIP_HELPER_DBG_PROC_SEL_MAC = 0,
|
|
CHIP_HELPER_DBG_PROC_SEL_PHY = 1,
|
|
CHIP_HELPER_DBG_PROC_SEL_BT = 2,
|
|
CHIP_HELPER_DBG_PROC_SEL_NONE = 2,
|
|
CHIP_HELPER_DBG_PROC_SEL_BOTH = 3
|
|
};
|
|
|
|
/* These are the only registers that we have to know the
|
|
address of before we know the chip version. */
|
|
enum chip_helper_fixed_registers
|
|
{
|
|
/* This is the address of GBL_CHIP_VERISON on BC7,
|
|
UF105x, UF60xx and
|
|
anything later than that. */
|
|
CHIP_HELPER_UNIFI_GBL_CHIP_VERSION = 0xFE81,
|
|
|
|
CHIP_HELPER_OLD_BLUECORE_GBL_CHIP_VERSION = 0xFF9A
|
|
|
|
/* This isn't used at the moment (but might be needed
|
|
to distinguish the BlueCore sub version?) */
|
|
/* CHIP_HELPER_OLD_BLUECORE_ANA_VERSION_ID = 0xFF7D */
|
|
};
|
|
|
|
/* Address-value pairs for defining initialisation values */
|
|
struct chip_helper_init_values
|
|
{
|
|
u16 addr;
|
|
u16 value;
|
|
};
|
|
|
|
/* A block of data that should be written to the device */
|
|
struct chip_helper_reset_values
|
|
{
|
|
u32 gp_address;
|
|
u32 len;
|
|
const u16 *data;
|
|
};
|
|
|
|
/*
|
|
* This is the C API.
|
|
*/
|
|
|
|
/* opaque type */
|
|
typedef const struct chip_device_desc_t ChipDescript;
|
|
|
|
/* Return a NULL descriptor */
|
|
ChipDescript* ChipHelper_Null(void);
|
|
|
|
/* This should get the correct version for any CSR chip.
|
|
The two parameters are what is read from addresses
|
|
0xFF9A and 0xFE81 (OLD_BLUECORE_GBL_CHIP_VERSION and
|
|
UNIFI_GBL_CHIP_VERSION). These should give a unique identity
|
|
for most (all?) chips.
|
|
|
|
FF9A is the old GBL_CHIP_VERSION register. If the high
|
|
eight bits are zero then the chip is a new (BC7 +) one
|
|
and FE81 is the _new_ GBL_CHIP_VERSION register. */
|
|
ChipDescript* ChipHelper_GetVersionAny(u16 from_FF9A, u16 from_FE81);
|
|
|
|
/* The chip is a UniFi, but we don't know which type
|
|
The parameter is the value of UNIFI_GBL_CHIP_VERSION (0xFE81) */
|
|
ChipDescript* ChipHelper_GetVersionUniFi(u16 version);
|
|
|
|
/* This gets the version from the SDIO device id. This only
|
|
gives quite a coarse grained version, so we should update once
|
|
we hav access to the function N registers. */
|
|
ChipDescript* ChipHelper_GetVersionSdio(u8 sdio_version);
|
|
|
|
/* The chip is some sort of BlueCore. If "age" is "pre_bc7" then
|
|
"version" is what was read from FF9A. If "age" is bc7_or_later
|
|
then "version" is read from FE81. If we don't know if we're pre
|
|
or post BC7 then we should use "GetVersionAny". */
|
|
ChipDescript* ChipHelper_GetVersionBlueCore(enum chip_helper_bluecore_age age,
|
|
u16 version);
|
|
|
|
/* The main functions of this class are built with an X macro. This
|
|
means we can generate the C and C++ versions from the same source
|
|
without the two diverging.
|
|
|
|
The DEF0 functions are simple and take no parameters. The first
|
|
parameter to the macro is the return type. The second parameter
|
|
is the function name and the third parameter is where to get the
|
|
info from (this is hidden from the user).
|
|
|
|
The DEF1 functions take one parameter. This time the third macro
|
|
parameter is the type of this parameter, and the fourth macro
|
|
parameter is the name of the parameter. The bodies of these
|
|
functions are hand written. */
|
|
#define CHIP_HELPER_LIST(m) \
|
|
CHIP_HELPER_DEF0(m, (const char *, FriendlyName, friendly_name)) \
|
|
CHIP_HELPER_DEF0(m, (const char *, MarketingName, marketing_name)) \
|
|
CHIP_HELPER_DEF0(m, (u16, DBG_EMU_CMD, regs->dbg_emu_cmd)) \
|
|
CHIP_HELPER_DEF0(m, (u16, DBG_HOST_PROC_SELECT, regs->host.dbg_proc_select)) \
|
|
CHIP_HELPER_DEF0(m, (u16, DBG_HOST_STOP_STATUS, regs->host.dbg_stop_status)) \
|
|
CHIP_HELPER_DEF0(m, (u16, HOST_WINDOW1_PAGE, regs->host.window1_page)) \
|
|
CHIP_HELPER_DEF0(m, (u16, HOST_WINDOW2_PAGE, regs->host.window2_page)) \
|
|
CHIP_HELPER_DEF0(m, (u16, HOST_WINDOW3_PAGE, regs->host.window3_page)) \
|
|
CHIP_HELPER_DEF0(m, (u16, HOST_IO_LOG_ADDR, regs->host.io_log_addr)) \
|
|
CHIP_HELPER_DEF0(m, (u16, DBG_SPI_PROC_SELECT, regs->spi.dbg_proc_select)) \
|
|
CHIP_HELPER_DEF0(m, (u16, DBG_SPI_STOP_STATUS, regs->spi.dbg_stop_status)) \
|
|
CHIP_HELPER_DEF0(m, (u16, SPI_WINDOW1_PAGE, regs->spi.window1_page)) \
|
|
CHIP_HELPER_DEF0(m, (u16, SPI_WINDOW2_PAGE, regs->spi.window2_page)) \
|
|
CHIP_HELPER_DEF0(m, (u16, SPI_WINDOW3_PAGE, regs->spi.window3_page)) \
|
|
CHIP_HELPER_DEF0(m, (u16, SPI_IO_LOG_ADDR, regs->spi.io_log_addr)) \
|
|
CHIP_HELPER_DEF0(m, (u16, DBG_RESET, regs->dbg_reset)) \
|
|
CHIP_HELPER_DEF0(m, (u16, DBG_RESET_VALUE, regs->dbg_reset_value)) \
|
|
CHIP_HELPER_DEF0(m, (u16, DBG_RESET_WARN, regs->dbg_reset_warn)) \
|
|
CHIP_HELPER_DEF0(m, (u16, DBG_RESET_WARN_VALUE, regs->dbg_reset_warn_value)) \
|
|
CHIP_HELPER_DEF0(m, (u16, DBG_RESET_RESULT, regs->dbg_reset_result)) \
|
|
CHIP_HELPER_DEF0(m, (u16, WATCHDOG_DISABLE, regs->watchdog_disable)) \
|
|
CHIP_HELPER_DEF0(m, (u16, PROC_PC_SNOOP, regs->proc_pc_snoop)) \
|
|
CHIP_HELPER_DEF0(m, (u16, GBL_CHIP_VERSION, regs->gbl_chip_version)) \
|
|
CHIP_HELPER_DEF0(m, (u16, GBL_MISC_ENABLES, regs->gbl_misc_enables)) \
|
|
CHIP_HELPER_DEF0(m, (u16, XAP_PCH, regs->xap_pch)) \
|
|
CHIP_HELPER_DEF0(m, (u16, XAP_PCL, regs->xap_pcl)) \
|
|
CHIP_HELPER_DEF0(m, (u16, MAILBOX0, regs->mailbox0)) \
|
|
CHIP_HELPER_DEF0(m, (u16, MAILBOX1, regs->mailbox1)) \
|
|
CHIP_HELPER_DEF0(m, (u16, MAILBOX2, regs->mailbox2)) \
|
|
CHIP_HELPER_DEF0(m, (u16, MAILBOX3, regs->mailbox3)) \
|
|
CHIP_HELPER_DEF0(m, (u16, SDIO_HIP_HANDSHAKE, regs->sdio_hip_handshake)) \
|
|
CHIP_HELPER_DEF0(m, (u16, SDIO_HOST_INT, regs->sdio_host_int)) \
|
|
CHIP_HELPER_DEF0(m, (u16, COEX_STATUS, regs->coex_status)) \
|
|
CHIP_HELPER_DEF0(m, (u16, SHARED_IO_INTERRUPT, regs->shared_io_interrupt)) \
|
|
CHIP_HELPER_DEF0(m, (u32, PROGRAM_MEMORY_RAM_OFFSET, prog_offset.ram)) \
|
|
CHIP_HELPER_DEF0(m, (u32, PROGRAM_MEMORY_ROM_OFFSET, prog_offset.rom)) \
|
|
CHIP_HELPER_DEF0(m, (u32, PROGRAM_MEMORY_FLASH_OFFSET, prog_offset.flash)) \
|
|
CHIP_HELPER_DEF0(m, (u32, PROGRAM_MEMORY_EXT_SRAM_OFFSET, prog_offset.ext_sram)) \
|
|
CHIP_HELPER_DEF0(m, (u16, DATA_MEMORY_RAM_OFFSET, data_offset.ram)) \
|
|
CHIP_HELPER_DEF0(m, (s32, HasFlash, bools.has_flash)) \
|
|
CHIP_HELPER_DEF0(m, (s32, HasExtSram, bools.has_ext_sram)) \
|
|
CHIP_HELPER_DEF0(m, (s32, HasRom, bools.has_rom)) \
|
|
CHIP_HELPER_DEF0(m, (s32, HasBt, bools.has_bt)) \
|
|
CHIP_HELPER_DEF0(m, (s32, HasWLan, bools.has_wlan)) \
|
|
CHIP_HELPER_DEF1(m, (u16, WINDOW_ADDRESS, enum chip_helper_window_index, window)) \
|
|
CHIP_HELPER_DEF1(m, (u16, WINDOW_SIZE, enum chip_helper_window_index, window)) \
|
|
CHIP_HELPER_DEF1(m, (u16, MapAddress_SPI2HOST, u16, addr)) \
|
|
CHIP_HELPER_DEF1(m, (u16, MapAddress_HOST2SPI, u16, addr)) \
|
|
CHIP_HELPER_DEF1(m, (u32, ClockStartupSequence, const struct chip_helper_init_values **, val)) \
|
|
CHIP_HELPER_DEF1(m, (u32, HostResetSequence, const struct chip_helper_reset_values **, val))
|
|
|
|
/* Some magic to help the expansion */
|
|
#define CHIP_HELPER_DEF0(a, b) \
|
|
CHIP_HELPER_DEF0_ ## a b
|
|
#define CHIP_HELPER_DEF1(a, b) \
|
|
CHIP_HELPER_DEF1_ ## a b
|
|
|
|
/* Macros so that when we expand the list we get "C" function prototypes. */
|
|
#define CHIP_HELPER_DEF0_C_DEC(ret_type, name, info) \
|
|
ret_type ChipHelper_ ## name(ChipDescript * chip_help);
|
|
#define CHIP_HELPER_DEF1_C_DEC(ret_type, name, type1, name1) \
|
|
ret_type ChipHelper_ ## name(ChipDescript * chip_help, type1 name1);
|
|
|
|
CHIP_HELPER_LIST(C_DEC)
|
|
|
|
/* FriendlyName
|
|
MarketingName
|
|
|
|
These two functions return human readable strings that describe
|
|
the chip. FriendlyName returns something that a software engineer
|
|
at CSR might understand. MarketingName returns something more like
|
|
an external name for a CSR chip.
|
|
*/
|
|
/* DBG_EMU_CMD
|
|
WATCHDOG_DISABLE
|
|
PROC_PC_SNOOP
|
|
GBL_CHIP_VERSION
|
|
XAP_PCH
|
|
XAP_PCL
|
|
|
|
These registers are used to control the XAPs.
|
|
*/
|
|
/* DBG_HOST_PROC_SELECT DBG_HOST_STOP_STATUS
|
|
HOST_WINDOW1_PAGE HOST_WINDOW2_PAGE HOST_WINDOW3_PAGE
|
|
HOST_IO_LOG_ADDR
|
|
DBG_SPI_PROC_SELECT DBG_SPI_STOP_STATUS
|
|
SPI_WINDOW1_PAGE SPI_WINDOW2_PAGE SPI_WINDOW3_PAGE
|
|
SPI_IO_LOG_ADDR
|
|
|
|
These register are used to control the XAPs and the memory
|
|
windows, normally while debugging the code on chip. There
|
|
are two versons of these registers, one for access via SPI
|
|
and another for access via the host interface.
|
|
*/
|
|
/* DBG_RESET
|
|
DBG_RESET_VALUE
|
|
DBG_RESET_WARN
|
|
DBG_RESET_WARN_VALUE
|
|
DBG_RESET_RESULT
|
|
|
|
These registers are used to reset the XAP. This can be
|
|
quite complex for some chips. If DBG_RESET_WARN is non
|
|
zero the DBG_RESET_WARN_VALUE should be written to address
|
|
DBG_RESET_WARN before the reset is perfeormed. DBG_RESET_VALUE
|
|
should then be written to DBG_RESET to make the reset happen.
|
|
The DBG_RESET_RESULT register should contain 0 if the reset
|
|
was successful.
|
|
*/
|
|
/* GBL_MISC_ENABLES
|
|
|
|
This register controls some special chip features. It
|
|
should be used with care is it changes quite a lot between
|
|
chip versions.
|
|
*/
|
|
/* MAILBOX0
|
|
MAILBOX1
|
|
MAILBOX2
|
|
MAILBOX3
|
|
|
|
The mailbox registers are for communication between the host
|
|
and the firmware. There use is described in part by the host
|
|
interface protcol specifcation.
|
|
*/
|
|
/* SDIO_HIP_HANDSHAKE
|
|
|
|
This is one of the more important SDIO HIP registers. On some
|
|
chips it has the same value as one of the mailbox registers
|
|
and on other chips it is different.
|
|
*/
|
|
/* SDIO_HOST_INT
|
|
SHARED_IO_INTERRUPT
|
|
|
|
These registers are used by some versions of the host interface
|
|
protocol specification. Their names should probably be changed
|
|
to hide the registers and to expose the functions more.
|
|
*/
|
|
/* COEX_STATUS
|
|
|
|
Coex status register, contains interrupt status and reset
|
|
pullup status. The latter is used to detect WAPI.
|
|
*/
|
|
/* PROGRAM_MEMORY_RAM_OFFSET
|
|
PROGRAM_MEMORY_ROM_OFFSET
|
|
PROGRAM_MEMORY_FLASH_OFFSET
|
|
PROGRAM_MEMORY_EXT_SRAM_OFFSET
|
|
DATA_MEMORY_RAM_OFFSET
|
|
|
|
These are constants that describe the offset of the different
|
|
memory types in the two different address spaces.
|
|
*/
|
|
/* HasFlash HasExtSram HasRom
|
|
HasBt HasWLan
|
|
|
|
These are a set of bools describing the chip.
|
|
*/
|
|
/* WINDOW_ADDRESS WINDOW_SIZE
|
|
|
|
These two functions return the size and address of the windows.
|
|
The address is the address of the lowest value in the address
|
|
map that is part of the window and the size is the number of
|
|
visible words.
|
|
|
|
Some of the windows have thier lowest portion covered by
|
|
registers. For these windows address is the first address
|
|
after the registers and size is the siave excluding the part
|
|
covered by registers.
|
|
*/
|
|
/* MapAddress_SPI2HOST
|
|
MapAddress_HOST2SPI
|
|
|
|
The debugging interface is duplicated on UniFi and later chips
|
|
so that there are two versions - one over the SPI interaface and
|
|
the other over the SDIO interface. These functions map the
|
|
registers between these two interfaces.
|
|
*/
|
|
/* ClockStartupSequence
|
|
|
|
This function returns the list of register value pairs that
|
|
should be forced into UniFi to enable SPI communication. This
|
|
set of registers is not needed if the firmware is running, but
|
|
will be needed if the device is being booted from cold. These
|
|
register writes enable the clocks and setup the PLL to a basic
|
|
working state. SPI access might be unreliable until these writes
|
|
have occured (And they may take mulitple goes).
|
|
*/
|
|
/* HostResetSequence
|
|
|
|
This returns a number of chunks of data and generic pointers.
|
|
All of the XAPs should be stopped. The data should be written
|
|
to the generic pointers. The instruction pointer for the MAC
|
|
should then be set to the start of program memory and then the
|
|
MAC should be "go"d. This will reset the chip in a reliable
|
|
and orderly manner without resetting the SDIO interface. It
|
|
is therefore not needed if the chip is being accessed by the
|
|
SPI interface (the DBG_RESET_ mechanism can be used instead).
|
|
*/
|
|
|
|
/* The Decode Window function is more complex. For the window
|
|
'window' it tries to return the address and page register
|
|
value needed to see offset 'offset' of memory type 'type'.
|
|
|
|
It return 1 on success and 0 on failure. 'page' is what
|
|
should be written to the page register. 'addr' is the
|
|
address in the XAPs 16 address map to read from. 'len'
|
|
is the length that we can read without having to change
|
|
the page registers. */
|
|
s32 ChipHelper_DecodeWindow(ChipDescript *chip_help,
|
|
enum chip_helper_window_index window,
|
|
enum chip_helper_window_type type,
|
|
u32 offset,
|
|
u16 *page, u16 *addr, u32 *len);
|
|
|
|
#endif
|