Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-block.git] / drivers / staging / csr / csr_wifi_hip_chiphelper.c
CommitLineData
635d2b00
GKH
1/*****************************************************************************
2
3 (c) Cambridge Silicon Radio Limited 2011
4 All rights reserved and confidential information of CSR
5
6 Refer to LICENSE.txt included with this source for details
7 on the license terms.
8
9*****************************************************************************/
10
980b5a2b 11#include "csr_macro.h"
635d2b00
GKH
12#include "csr_wifi_hip_chiphelper_private.h"
13
14#ifndef nelem
15#define nelem(a) (sizeof(a) / sizeof(a[0]))
16#endif
17
18#define counted(foo) { nelem(foo), foo }
19#define null_counted() { 0, NULL }
20
21/* The init values are a set of register writes that we must
22 perform when we first connect to the chip to get it working.
23 They swicth on the correct clocks and possibly set the host
24 interface as a wkaeup source. They should not be used if
25 proper HIP opperation is required, but are useful before we
26 do a code download. */
27static const struct chip_helper_init_values init_vals_v1[] = {
28 { 0xFDBB, 0xFFFF },
29 { 0xFDB6, 0x03FF },
30 { 0xFDB1, 0x01E3 },
31 { 0xFDB3, 0x0FFF },
32 { 0xFEE3, 0x08F0 },
33 { 0xFEE7, 0x3C3F },
34 { 0xFEE6, 0x0050 },
35 { 0xFDBA, 0x0000 }
36};
37
38static const struct chip_helper_init_values init_vals_v2[] = {
39 { 0xFDB6, 0x0FFF },
40 { 0xF023, 0x3F3F },
41 { 0xFDB1, 0x01E3 },
42 { 0xFDB3, 0x0FFF },
43 { 0xF003, 0x08F0 },
44 { 0xF007, 0x3C3F },
45 { 0xF006, 0x0050 }
46};
47
48
49static const struct chip_helper_init_values init_vals_v22_v23[] = {
50 { 0xF81C, 0x00FF },
51 /*{ 0x????, 0x???? }, */
52 { 0xF80C, 0x1FFF },
53 { 0xFA25, 0x001F },
54 { 0xF804, 0x00FF },
55 { 0xF802, 0x0FFF },
56 /*{ 0x????, 0x???? },
57 { 0x????, 0x???? },
58 { 0x????, 0x???? }*/
59};
60
8c87f69a 61static const u16 reset_program_a_v1_or_v2[] = {
635d2b00
GKH
62 0x0000
63};
8c87f69a 64static const u16 reset_program_b_v1_or_v2[] = {
635d2b00
GKH
65 0x0010, 0xFE00, 0xA021, 0xFF00, 0x8111, 0x0009, 0x0CA4, 0x0114,
66 0x0280, 0x04F8, 0xFE00, 0x6F25, 0x06E0, 0x0010, 0xFC00, 0x0121,
67 0xFC00, 0x0225, 0xFE00, 0x7125, 0xFE00, 0x6D11, 0x03F0, 0xFE00,
68 0x6E25, 0x0008, 0x00E0
69};
70
71static const struct chip_helper_reset_values reset_program_v1_or_v2[] =
72{
73 {
74 MAKE_GP(REGISTERS, 0x000C),
75 nelem(reset_program_a_v1_or_v2),
76 reset_program_a_v1_or_v2
77 },
78 {
79 MAKE_GP(MAC_PMEM, 0x000000),
80 nelem(reset_program_b_v1_or_v2),
81 reset_program_b_v1_or_v2
82 }
83};
84
85static const struct chip_map_address_t unifi_map_address_v1_v2[] =
86{
87 { 0xFE9F, 0xFE7B }, /* PM1_BANK_SELECT */
88 { 0xFE9E, 0xFE78 }, /* PM2_BANK_SELECT */
89 { 0xFE9D, 0xFE7E }, /* SHARED_DMEM_PAGE */
90 { 0xFE91, 0xFE90 }, /* PROC_SELECT */
91 { 0xFE8D, 0xFE8C }, /* STOP_STATUS */
92};
93
94static const struct chip_map_address_t unifi_map_address_v22_v23[] =
95{
96 { 0xF8F9, 0xF8AC }, /* GW1_CONFIG */
97 { 0xF8FA, 0xF8AD }, /* GW2_CONFIG */
98 { 0xF8FB, 0xF8AE }, /* GW3_CONFIG */
99 { 0xF830, 0xF81E }, /* PROC_SELECT */
100 { 0xF831, 0xF81F }, /* STOP_STATUS */
101 { 0xF8FC, 0xF8AF }, /* IO_LOG_ADDRESS */
102};
103
104static const struct chip_device_regs_t unifi_device_regs_null =
105{
106 0xFE81, /* GBL_CHIP_VERSION */
107 0x0000, /* GBL_MISC_ENABLES */
108 0x0000, /* DBG_EMU_CMD */
109 {
110 0x0000, /* HOST.DBG_PROC_SELECT */
111 0x0000, /* HOST.DBG_STOP_STATUS */
112 0x0000, /* HOST.WINDOW1_PAGE */
113 0x0000, /* HOST.WINDOW2_PAGE */
114 0x0000, /* HOST.WINDOW3_PAGE */
115 0x0000 /* HOST.IO_LOG_ADDR */
116 },
117 {
118 0x0000, /* SPI.DBG_PROC_SELECT */
119 0x0000, /* SPI.DBG_STOP_STATUS */
120 0x0000, /* SPI.WINDOW1_PAGE */
121 0x0000, /* SPI.WINDOW2_PAGE */
122 0x0000, /* SPI.WINDOW3_PAGE */
123 0x0000 /* SPI.IO_LOG_ADDR */
124 },
125 0x0000, /* DBG_RESET */
126 0x0000, /* > DBG_RESET_VALUE */
127 0x0000, /* DBG_RESET_WARN */
128 0x0000, /* DBG_RESET_WARN_VALUE */
129 0x0000, /* DBG_RESET_RESULT */
130 0xFFE9, /* XAP_PCH */
131 0xFFEA, /* XAP_PCL */
132 0x0000, /* PROC_PC_SNOOP */
133 0x0000, /* WATCHDOG_DISABLE */
134 0x0000, /* MAILBOX0 */
135 0x0000, /* MAILBOX1 */
136 0x0000, /* MAILBOX2 */
137 0x0000, /* MAILBOX3 */
138 0x0000, /* SDIO_HOST_INT */
139 0x0000, /* SHARED_IO_INTERRUPT */
140 0x0000, /* SDIO HIP HANDSHAKE */
141 0x0000 /* COEX_STATUS */
142};
143
144/* UF105x */
145static const struct chip_device_regs_t unifi_device_regs_v1 =
146{
147 0xFE81, /* GBL_CHIP_VERSION */
148 0xFE87, /* GBL_MISC_ENABLES */
149 0xFE9C, /* DBG_EMU_CMD */
150 {
151 0xFE90, /* HOST.DBG_PROC_SELECT */
152 0xFE8C, /* HOST.DBG_STOP_STATUS */
153 0xFE7B, /* HOST.WINDOW1_PAGE */
154 0xFE78, /* HOST.WINDOW2_PAGE */
155 0xFE7E, /* HOST.WINDOW3_PAGE */
156 0x0000 /* HOST.IO_LOG_ADDR */
157 },
158 {
159 0xFE91, /* SPI.DBG_PROC_SELECT */
160 0xFE8D, /* SPI.DBG_STOP_STATUS */
161 0xFE9F, /* SPI.WINDOW1_PAGE */
162 0xFE9E, /* SPI.WINDOW2_PAGE */
163 0xFE9D, /* SPI.WINDOW3_PAGE */
164 0x0000 /* SPI.IO_LOG_ADDR */
165 },
166 0xFE92, /* DBG_RESET */
167 0x0001, /* > DBG_RESET_VALUE */
168 0xFDA0, /* DBG_RESET_WARN (HOST_SELECT) */
169 0x0000, /* DBG_RESET_WARN_VALUE */
170 0xFE92, /* DBG_RESET_RESULT */
171 0xFFE9, /* XAP_PCH */
172 0xFFEA, /* XAP_PCL */
173 0x0051, /* PROC_PC_SNOOP */
174 0xFE70, /* WATCHDOG_DISABLE */
175 0xFE6B, /* MAILBOX0 */
176 0xFE6A, /* MAILBOX1 */
177 0xFE69, /* MAILBOX2 */
178 0xFE68, /* MAILBOX3 */
179 0xFE67, /* SDIO_HOST_INT */
180 0xFE65, /* SHARED_IO_INTERRUPT */
181 0xFDE9, /* SDIO HIP HANDSHAKE */
182 0x0000 /* COEX_STATUS */
183};
184
185/* UF2... */
186static const struct chip_device_regs_t unifi_device_regs_v2 =
187{
188 0xFE81, /* GBL_CHIP_VERSION */
189 0xFE87, /* GBL_MISC_ENABLES */
190 0xFE9C, /* DBG_EMU_CMD */
191 {
192 0xFE90, /* HOST.DBG_PROC_SELECT */
193 0xFE8C, /* HOST.DBG_STOP_STATUS */
194 0xFE7B, /* HOST.WINDOW1_PAGE */
195 0xFE78, /* HOST.WINDOW2_PAGE */
196 0xFE7E, /* HOST.WINDOW3_PAGE */
197 0x0000 /* HOST.IO_LOG_ADDR */
198 },
199 {
200 0xFE91, /* SPI.DBG_PROC_SELECT */
201 0xFE8D, /* SPI.DBG_STOP_STATUS */
202 0xFE9F, /* SPI.WINDOW1_PAGE */
203 0xFE9E, /* SPI.WINDOW2_PAGE */
204 0xFE9D, /* SPI.WINDOW3_PAGE */
205 0x0000 /* SPI.IO_LOG_ADDR */
206 },
207 0xFE92, /* DBG_RESET */
208 0x0000, /* > DBG_RESET_VALUE */
209 0xFDE9, /* DBG_RESET_WARN (TEST_FLASH_DATA - SHARED_MAILBOX2B) */
210 0xFFFF, /* DBG_RESET_WARN_VALUE */
211 0xFDE9, /* DBG_RESET_RESULT (TEST_FLASH_DATA) */
212 0xFFE9, /* XAP_PCH */
213 0xFFEA, /* XAP_PCL */
214 0x0051, /* PROC_PC_SNOOP */
215 0xFE70, /* WATCHDOG_DISABLE */
216 0xFE6B, /* MAILBOX0 */
217 0xFE6A, /* MAILBOX1 */
218 0xFE69, /* MAILBOX2 */
219 0xFE68, /* MAILBOX3 */
220 0xFE67, /* SDIO_HOST_INT */
221 0xFE65, /* SHARED_IO_INTERRUPT */
222 0xFE69, /* SDIO HIP HANDSHAKE */
223 0x0000 /* COEX_STATUS */
224};
225
226/* UF60xx */
227static const struct chip_device_regs_t unifi_device_regs_v22_v23 =
228{
229 0xFE81, /* GBL_CHIP_VERSION */
230 0xF84F, /* GBL_MISC_ENABLES */
231 0xF81D, /* DBG_EMU_CMD */
232 {
233 0xF81E, /* HOST.DBG_PROC_SELECT */
234 0xF81F, /* HOST.DBG_STOP_STATUS */
235 0xF8AC, /* HOST.WINDOW1_PAGE */
236 0xF8AD, /* HOST.WINDOW2_PAGE */
237 0xF8AE, /* HOST.WINDOW3_PAGE */
238 0xF8AF /* HOST.IO_LOG_ADDR */
239 },
240 {
241 0xF830, /* SPI.DBG_PROC_SELECT */
242 0xF831, /* SPI.DBG_STOP_STATUS */
243 0xF8F9, /* SPI.WINDOW1_PAGE */
244 0xF8FA, /* SPI.WINDOW2_PAGE */
245 0xF8FB, /* SPI.WINDOW3_PAGE */
246 0xF8FC /* SPI.IO_LOG_ADDR */
247 },
248 0xF82F, /* DBG_RESET */
249 0x0001, /* > DBG_RESET_VALUE */
250 0x0000, /* DBG_RESET_WARN */
251 0x0000, /* DBG_RESET_WARN_VALUE */
252 0xF82F, /* DBG_RESET_RESULT */
253 0xFFE9, /* XAP_PCH */
254 0xFFEA, /* XAP_PCL */
255 0x001B, /* PROC_PC_SNOOP */
256 0x0055, /* WATCHDOG_DISABLE */
257 0xF84B, /* MAILBOX0 */
258 0xF84C, /* MAILBOX1 */
259 0xF84D, /* MAILBOX2 */
260 0xF84E, /* MAILBOX3 */
261 0xF92F, /* SDIO_HOST_INT */
262 0xF92B, /* SDIO_FROMHOST_SCRTACH0 / SHARED_IO_INTERRUPT */
263 0xF84D, /* SDIO HIP HANDSHAKE (MAILBOX2) */
264 0xF9FB /* COEX_STATUS */
265};
266
267/* Program memory window on UF105x. */
268static const struct window_shift_info_t prog_window_array_unifi_v1_v2[CHIP_HELPER_WT_COUNT] =
269{
270 { TRUE, 11, 0x0200 }, /* CODE RAM */
271 { TRUE, 11, 0x0000 }, /* FLASH */
272 { TRUE, 11, 0x0400 }, /* External SRAM */
273 { FALSE, 0, 0 }, /* ROM */
274 { FALSE, 0, 0 } /* SHARED */
275};
276
277/* Shared memory window on UF105x. */
278static const struct window_shift_info_t shared_window_array_unifi_v1_v2[CHIP_HELPER_WT_COUNT] =
279{
280 { FALSE, 0, 0 }, /* CODE RAM */
281 { FALSE, 0, 0 }, /* FLASH */
282 { FALSE, 0, 0 }, /* External SRAM */
283 { FALSE, 0, 0 }, /* ROM */
284 { TRUE, 11, 0x0000 } /* SHARED */
285};
286
287/* One of the Generic Windows on UF60xx and later. */
288static const struct window_shift_info_t generic_window_array_unifi_v22_v23[CHIP_HELPER_WT_COUNT] =
289{
290 { TRUE, 11, 0x3800 }, /* CODE RAM */
291 { FALSE, 0, 0 }, /* FLASH */
292 { FALSE, 0, 0 }, /* External SRAM */
293 { TRUE, 11, 0x2000 }, /* ROM */
294 { TRUE, 11, 0x0000 } /* SHARED */
295};
296
297/* The three windows on UF105x. */
298static const struct window_info_t prog1_window_unifi_v1_v2 = { 0x0000, 0x2000, 0x0080, prog_window_array_unifi_v1_v2 };
299static const struct window_info_t prog2_window_unifi_v1_v2 = { 0x2000, 0x2000, 0x0000, prog_window_array_unifi_v1_v2 };
300static const struct window_info_t shared_window_unifi_v1_v2 = { 0x4000, 0x2000, 0x0000, shared_window_array_unifi_v1_v2 };
301
302/* The three windows on UF60xx and later. */
303static const struct window_info_t generic1_window_unifi_v22_v23 = { 0x0000, 0x2000, 0x0080, generic_window_array_unifi_v22_v23 };
304static const struct window_info_t generic2_window_unifi_v22_v23 = { 0x2000, 0x2000, 0x0000, generic_window_array_unifi_v22_v23 };
305static const struct window_info_t generic3_window_unifi_v22_v23 = { 0x4000, 0x2000, 0x0000, generic_window_array_unifi_v22_v23 };
306
307static const struct chip_device_desc_t chip_device_desc_null =
308{
309 { FALSE, 0x0000, 0x0000, 0x00 },
310 "",
311 "",
312 null_counted(), /* init */
313 null_counted(), /* reset_prog */
314 &unifi_device_regs_null, /* regs */
315 {
316 FALSE, /* has_flash */
317 FALSE, /* has_ext_sram */
318 FALSE, /* has_rom */
319 FALSE, /* has_bt */
320 FALSE, /* has_wlan */
321 },
322 null_counted(),
323 /* prog_offset */
324 {
325 0x00000000,
326 0x00000000,
327 0x00000000,
328 0x00000000
329 },
330 /* data_offset */
331 {
332 0x0000 /* ram */
333 },
334 /* windows */
335 {
336 NULL,
337 NULL,
338 NULL
339 }
340};
341
342static const struct chip_device_desc_t unifi_device_desc_v1 =
343{
344 { FALSE, 0xf0ff, 0x1001, 0x01 }, /* UF105x R01 */
345 "UF105x",
346 "UniFi-1",
347 counted(init_vals_v1), /* init */
348 counted(reset_program_v1_or_v2), /* reset_prog */
349 &unifi_device_regs_v1, /* regs */
350 {
351 TRUE, /* has_flash */
352 TRUE, /* has_ext_sram */
353 FALSE, /* has_rom */
354 FALSE, /* has_bt */
355 TRUE, /* has_wlan */
356 },
357 counted(unifi_map_address_v1_v2), /* map */
358 /* prog_offset */
359 {
360 0x00100000, /* ram */
361 0x00000000, /* rom (invalid) */
362 0x00000000, /* flash */
363 0x00200000, /* ext_ram */
364 },
365 /* data_offset */
366 {
367 0x8000 /* ram */
368 },
369 /* windows */
370 {
371 &prog1_window_unifi_v1_v2,
372 &prog2_window_unifi_v1_v2,
373 &shared_window_unifi_v1_v2
374 }
375};
376
377static const struct chip_device_desc_t unifi_device_desc_v2 =
378{
379 { FALSE, 0xf0ff, 0x2001, 0x02 }, /* UF2... R02 */
380 "UF2...",
381 "UniFi-2",
382 counted(init_vals_v2), /* init */
383 counted(reset_program_v1_or_v2), /* reset_prog */
384 &unifi_device_regs_v2, /* regs */
385 {
386 TRUE, /* has_flash */
387 TRUE, /* has_ext_sram */
388 FALSE, /* has_rom */
389 FALSE, /* has_bt */
390 TRUE, /* has_wlan */
391 },
392 counted(unifi_map_address_v1_v2), /* map */
393 /* prog_offset */
394 {
395 0x00100000, /* ram */
396 0x00000000, /* rom (invalid) */
397 0x00000000, /* flash */
398 0x00200000, /* ext_ram */
399 },
400 /* data_offset */
401 {
402 0x8000 /* ram */
403 },
404 /* windows */
405 {
406 &prog1_window_unifi_v1_v2,
407 &prog2_window_unifi_v1_v2,
408 &shared_window_unifi_v1_v2
409 }
410};
411
412static const struct chip_device_desc_t unifi_device_desc_v3 =
413{
414 { FALSE, 0xf0ff, 0x3001, 0x02 }, /* UF2... R03 */
415 "UF2...",
416 "UniFi-3",
417 counted(init_vals_v2), /* init */
418 counted(reset_program_v1_or_v2), /* reset_prog */
419 &unifi_device_regs_v2, /* regs */
420 {
421 TRUE, /* has_flash */
422 TRUE, /* has_ext_sram */
423 FALSE, /* has_rom */
424 FALSE, /* has_bt */
425 TRUE, /* has_wlan */
426 },
427 counted(unifi_map_address_v1_v2), /* map */
428 /* prog_offset */
429 {
430 0x00100000, /* ram */
431 0x00000000, /* rom (invalid) */
432 0x00000000, /* flash */
433 0x00200000, /* ext_ram */
434 },
435 /* data_offset */
436 {
437 0x8000 /* ram */
438 },
439 /* windows */
440 {
441 &prog1_window_unifi_v1_v2,
442 &prog2_window_unifi_v1_v2,
443 &shared_window_unifi_v1_v2
444 }
445};
446
447static const struct chip_device_desc_t unifi_device_desc_v22 =
448{
449 { FALSE, 0x00ff, 0x0022, 0x07 }, /* UF60xx */
450 "UF60xx",
451 "UniFi-4",
452 counted(init_vals_v22_v23), /* init */
453 null_counted(), /* reset_prog */
454 &unifi_device_regs_v22_v23, /* regs */
455 {
456 FALSE, /* has_flash */
457 FALSE, /* has_ext_sram */
458 TRUE, /* has_rom */
459 FALSE, /* has_bt */
460 TRUE, /* has_wlan */
461 },
462 counted(unifi_map_address_v22_v23), /* map */
463 /* prog_offset */
464 {
465 0x00C00000, /* ram */
466 0x00000000, /* rom */
467 0x00000000, /* flash (invalid) */
468 0x00000000, /* ext_ram (invalid) */
469 },
470 /* data_offset */
471 {
472 0x8000 /* ram */
473 },
474 /* windows */
475 {
476 &generic1_window_unifi_v22_v23,
477 &generic2_window_unifi_v22_v23,
478 &generic3_window_unifi_v22_v23
479 }
480};
481
482static const struct chip_device_desc_t unifi_device_desc_v23 =
483{
484 { FALSE, 0x00ff, 0x0023, 0x08 }, /* UF.... */
485 "UF....",
486 "UF.... (5)",
487 counted(init_vals_v22_v23), /* init */
488 null_counted(), /* reset_prog */
489 &unifi_device_regs_v22_v23, /* regs */
490 {
491 FALSE, /* has_flash */
492 FALSE, /* has_ext_sram */
493 TRUE, /* has_rom */
494 TRUE, /* has_bt */
495 TRUE, /* has_wlan */
496 },
497 counted(unifi_map_address_v22_v23),
498 /* prog_offset */
499 {
500 0x00C00000, /* ram */
501 0x00000000, /* rom */
502 0x00000000, /* flash (invalid) */
503 0x00000000, /* ext_sram (invalid) */
504 },
505 /* data_offset */
506 {
507 0x8000 /* ram */
508 },
509 /* windows */
510 {
511 &generic1_window_unifi_v22_v23,
512 &generic2_window_unifi_v22_v23,
513 &generic3_window_unifi_v22_v23
514 }
515};
516
517static const struct chip_device_desc_t hyd_wlan_subsys_desc_v1 =
518{
519 { FALSE, 0x00ff, 0x0044, 0x00 }, /* UF.... */
520 "HYD...",
521 "HYD... ",
522 counted(init_vals_v22_v23), /* init */
523 null_counted(), /* reset_prog */
524 &unifi_device_regs_v22_v23, /* regs */
525 {
526 FALSE, /* has_flash */
527 FALSE, /* has_ext_sram */
528 TRUE, /* has_rom */
529 FALSE, /* has_bt */
530 TRUE, /* has_wlan */
531 },
532 counted(unifi_map_address_v22_v23),
533 /* prog_offset */
534 {
535 0x00C00000, /* ram */
536 0x00000000, /* rom */
537 0x00000000, /* flash (invalid) */
538 0x00000000, /* ext_sram (invalid) */
539 },
540 /* data_offset */
541 {
542 0x8000 /* ram */
543 },
544 /* windows */
545 {
546 &generic1_window_unifi_v22_v23,
547 &generic2_window_unifi_v22_v23,
548 &generic3_window_unifi_v22_v23
549 }
550};
551
552
553/* This is the list of all chips that we know about. I'm
554 assuming that the order here will be important - we
555 might have multiple entries witrh the same SDIO id for
556 instance. The first one in this list will be the one
557 that is returned if a search is done on only that id.
558 The client will then have to call GetVersionXXX again
559 but with more detailed info.
560
561 I don't know if we need to signal this up to the client
562 in some way?
563
564 (We get the SDIO id before we know anything else about
565 the chip. We might not be able to read any of the other
566 registers at first, but we still need to know about the
567 chip). */
568static const struct chip_device_desc_t *chip_ver_to_desc[] =
569{
570 &unifi_device_desc_v1, /* UF105x R01 */
571 &unifi_device_desc_v2, /* UF2... R02 */
572 &unifi_device_desc_v3, /* UF2... R03 */
573 &unifi_device_desc_v22, /* UF60xx */
574 &unifi_device_desc_v23, /* UF.... */
575 &hyd_wlan_subsys_desc_v1
576};
577
7e6f5794 578ChipDescript* ChipHelper_GetVersionSdio(u8 sdio_ver)
635d2b00 579{
26a6b2e1 580 u32 i;
635d2b00
GKH
581
582 for (i = 0; i < nelem(chip_ver_to_desc); i++)
583 {
584 if (chip_ver_to_desc[i]->chip_version.sdio == sdio_ver)
585 {
586 return chip_ver_to_desc[i];
587 }
588 }
589
590 return &chip_device_desc_null;
591}
592
593
8c87f69a 594ChipDescript* ChipHelper_GetVersionAny(u16 from_FF9A, u16 from_FE81)
635d2b00 595{
26a6b2e1 596 u32 i;
635d2b00
GKH
597
598 if ((from_FF9A & 0xFF00) != 0)
599 {
600 for (i = 0; i < nelem(chip_ver_to_desc); i++)
601 {
602 if (chip_ver_to_desc[i]->chip_version.pre_bc7 &&
603 ((from_FF9A & chip_ver_to_desc[i]->chip_version.mask) ==
604 chip_ver_to_desc[i]->chip_version.result))
605 {
606 return chip_ver_to_desc[i];
607 }
608 }
609 }
610 else
611 {
612 for (i = 0; i < nelem(chip_ver_to_desc); i++)
613 {
614 if (!chip_ver_to_desc[i]->chip_version.pre_bc7 &&
615 ((from_FE81 & chip_ver_to_desc[i]->chip_version.mask) ==
616 chip_ver_to_desc[i]->chip_version.result))
617 {
618 return chip_ver_to_desc[i];
619 }
620 }
621 }
622
623 return &chip_device_desc_null;
624}
625
626
8c87f69a 627ChipDescript* ChipHelper_GetVersionUniFi(u16 ver)
635d2b00
GKH
628{
629 return ChipHelper_GetVersionAny(0x0000, ver);
630}
631
632
47ec4ed2 633ChipDescript *ChipHelper_Null(void)
635d2b00
GKH
634{
635 return &chip_device_desc_null;
636}
637
638
8c87f69a 639ChipDescript* ChipHelper_GetVersionBlueCore(enum chip_helper_bluecore_age bc_age, u16 version)
635d2b00
GKH
640{
641 if (bc_age == chip_helper_bluecore_pre_bc7)
642 {
643 return ChipHelper_GetVersionAny(version, 0x0000);
644 }
645 else
646 {
647 return ChipHelper_GetVersionAny(0x0000, version);
648 }
649}
650
651
652/* Expand the DEF0 functions into simple code to return the
653 correct thing. The DEF1 functions expand to nothing in
654 this X macro expansion. */
655#define CHIP_HELPER_DEF0_C_DEF(ret_type, name, info) \
656 ret_type ChipHelper_ ## name(ChipDescript * chip_help) \
657 { \
658 return chip_help->info; \
659 }
660#define CHIP_HELPER_DEF1_C_DEF(ret_type, name, type1, name1)
661
662CHIP_HELPER_LIST(C_DEF)
663
664/*
665 * Map register addresses between HOST and SPI access.
666 */
8c87f69a 667u16 ChipHelper_MapAddress_SPI2HOST(ChipDescript *chip_help, u16 addr)
635d2b00 668{
26a6b2e1 669 u32 i;
635d2b00
GKH
670 for (i = 0; i < chip_help->map.len; i++)
671 {
672 if (chip_help->map.vals[i].spi == addr)
673 {
674 return chip_help->map.vals[i].host;
675 }
676 }
677 return addr;
678}
679
680
8c87f69a 681u16 ChipHelper_MapAddress_HOST2SPI(ChipDescript *chip_help, u16 addr)
635d2b00 682{
26a6b2e1 683 u32 i;
635d2b00
GKH
684 for (i = 0; i < chip_help->map.len; i++)
685 {
686 if (chip_help->map.vals[i].host == addr)
687 {
688 return chip_help->map.vals[i].spi;
689 }
690 }
691 return addr;
692}
693
694
695/* The address returned by this function is the start of the
696 window in the address space, that is where we can start
697 accessing data from. If a section of the window at the
698 start is unusable because something else is cluttering up
699 the address map then that is taken into account and this
700 function returns that address justt past that. */
8c87f69a 701u16 ChipHelper_WINDOW_ADDRESS(ChipDescript *chip_help,
635d2b00
GKH
702 enum chip_helper_window_index window)
703{
704 if (window < CHIP_HELPER_WINDOW_COUNT &&
705 chip_help->windows[window] != NULL)
706 {
707 return chip_help->windows[window]->address + chip_help->windows[window]->blocked;
708 }
709 return 0;
710}
711
712
713/* This returns the size of the window minus any blocked section */
8c87f69a 714u16 ChipHelper_WINDOW_SIZE(ChipDescript *chip_help,
635d2b00
GKH
715 enum chip_helper_window_index window)
716{
717 if (window < CHIP_HELPER_WINDOW_COUNT &&
718 chip_help->windows[window] != NULL)
719 {
720 return chip_help->windows[window]->size - chip_help->windows[window]->blocked;
721 }
722 return 0;
723}
724
725
726/* Get the register writes we should do to make sure that
727 the chip is running with most clocks on. */
26a6b2e1 728u32 ChipHelper_ClockStartupSequence(ChipDescript *chip_help,
635d2b00
GKH
729 const struct chip_helper_init_values **val)
730{
731 *val = chip_help->init.vals;
732 return chip_help->init.len;
733}
734
735
736/* Get the set of values tat we should write to the chip to perform a reset. */
26a6b2e1 737u32 ChipHelper_HostResetSequence(ChipDescript *chip_help,
635d2b00
GKH
738 const struct chip_helper_reset_values **val)
739{
740 *val = chip_help->reset_prog.vals;
741 return chip_help->reset_prog.len;
742}
743
744
745/* Decode a windowed access to the chip. */
95e326c2 746s32 ChipHelper_DecodeWindow(ChipDescript *chip_help,
635d2b00
GKH
747 enum chip_helper_window_index window,
748 enum chip_helper_window_type type,
26a6b2e1
GKH
749 u32 offset,
750 u16 *page, u16 *addr, u32 *len)
635d2b00
GKH
751{
752 const struct window_info_t *win;
753 const struct window_shift_info_t *mode;
8c87f69a 754 u16 of, pg;
635d2b00
GKH
755
756 if (window >= CHIP_HELPER_WINDOW_COUNT)
757 {
758 return FALSE;
759 }
760 if ((win = chip_help->windows[window]) == NULL)
761 {
762 return FALSE;
763 }
764 if (type >= CHIP_HELPER_WT_COUNT)
765 {
766 return FALSE;
767 }
768 if ((mode = &win->mode[type]) == NULL)
769 {
770 return FALSE;
771 }
772 if (!mode->allowed)
773 {
774 return FALSE;
775 }
776
8c87f69a
GKH
777 pg = (u16)(offset >> mode->page_shift) + mode->page_offset;
778 of = (u16)(offset & ((1 << mode->page_shift) - 1));
635d2b00
GKH
779 /* If 'blocked' is zero this does nothing, else decrease
780 the page register and increase the offset until we aren't
781 in the blocked region of the window. */
782 while (of < win->blocked)
783 {
784 of += 1 << mode->page_shift;
785 pg--;
786 }
787 *page = pg;
788 *addr = win->address + of;
789 *len = win->size - of;
790 return TRUE;
791}
792
793