aboutsummaryrefslogtreecommitdiff
path: root/drivers/staging/csr/csr_wifi_hip_chiphelper.h
blob: b6b67ee11db8bbdd1ee804c8800527f49d6fd665 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
/*****************************************************************************

            (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