linux/drivers/staging/csr/csr_wifi_hip_chiphelper.c
<<
>>
Prefs
   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