Root/drivers/staging/csr/csr_wifi_hip_chiphelper.c

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
11#include "csr_macro.h"
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
61static const u16 reset_program_a_v1_or_v2[] = {
62    0x0000
63};
64static const u16 reset_program_b_v1_or_v2[] = {
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
578ChipDescript* ChipHelper_GetVersionSdio(u8 sdio_ver)
579{
580    u32 i;
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
594ChipDescript* ChipHelper_GetVersionAny(u16 from_FF9A, u16 from_FE81)
595{
596    u32 i;
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
627ChipDescript* ChipHelper_GetVersionUniFi(u16 ver)
628{
629    return ChipHelper_GetVersionAny(0x0000, ver);
630}
631
632
633ChipDescript *ChipHelper_Null(void)
634{
635    return &chip_device_desc_null;
636}
637
638
639ChipDescript* ChipHelper_GetVersionBlueCore(enum chip_helper_bluecore_age bc_age, u16 version)
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 */
667u16 ChipHelper_MapAddress_SPI2HOST(ChipDescript *chip_help, u16 addr)
668{
669    u32 i;
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
681u16 ChipHelper_MapAddress_HOST2SPI(ChipDescript *chip_help, u16 addr)
682{
683    u32 i;
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. */
701u16 ChipHelper_WINDOW_ADDRESS(ChipDescript *chip_help,
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 */
714u16 ChipHelper_WINDOW_SIZE(ChipDescript *chip_help,
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. */
728u32 ChipHelper_ClockStartupSequence(ChipDescript *chip_help,
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. */
737u32 ChipHelper_HostResetSequence(ChipDescript *chip_help,
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. */
746s32 ChipHelper_DecodeWindow(ChipDescript *chip_help,
747                                 enum chip_helper_window_index window,
748                                 enum chip_helper_window_type type,
749                                 u32 offset,
750                                 u16 *page, u16 *addr, u32 *len)
751{
752    const struct window_info_t *win;
753    const struct window_shift_info_t *mode;
754    u16 of, pg;
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
777    pg = (u16)(offset >> mode->page_shift) + mode->page_offset;
778    of = (u16)(offset & ((1 << mode->page_shift) - 1));
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
794

Archive Download this file



interactive