Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
csr_wifi_hip_chiphelper.c
Go to the documentation of this file.
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"
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. */
27 static 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 
38 static 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 
49 static 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 
61 static const u16 reset_program_a_v1_or_v2[] = {
62  0x0000
63 };
64 static 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 
71 static 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 
85 static 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 
94 static 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 
104 static 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 */
145 static 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... */
186 static 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 */
227 static 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. */
268 static 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. */
278 static 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. */
288 static 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. */
298 static const struct window_info_t prog1_window_unifi_v1_v2 = { 0x0000, 0x2000, 0x0080, prog_window_array_unifi_v1_v2 };
299 static const struct window_info_t prog2_window_unifi_v1_v2 = { 0x2000, 0x2000, 0x0000, prog_window_array_unifi_v1_v2 };
300 static 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. */
303 static const struct window_info_t generic1_window_unifi_v22_v23 = { 0x0000, 0x2000, 0x0080, generic_window_array_unifi_v22_v23 };
304 static const struct window_info_t generic2_window_unifi_v22_v23 = { 0x2000, 0x2000, 0x0000, generic_window_array_unifi_v22_v23 };
305 static const struct window_info_t generic3_window_unifi_v22_v23 = { 0x4000, 0x2000, 0x0000, generic_window_array_unifi_v22_v23 };
306 
307 static 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 
342 static 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 
377 static 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 
412 static 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 
447 static 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 
482 static 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 
517 static 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). */
568 static 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 
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 
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 
628 {
629  return ChipHelper_GetVersionAny(0x0000, ver);
630 }
631 
632 
634 {
635  return &chip_device_desc_null;
636 }
637 
638 
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 
662 CHIP_HELPER_LIST(C_DEF)
663 
664 /*
665  * Map register addresses between HOST and SPI access.
666  */
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 
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. */
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 */
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. */
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. */
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. */
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