Home | History | Annotate | Download | only in hal
      1 /******************************************************************************
      2  *
      3  *  Copyright (C) 2012-2014 Broadcom Corporation
      4  *
      5  *  Licensed under the Apache License, Version 2.0 (the "License");
      6  *  you may not use this file except in compliance with the License.
      7  *  You may obtain a copy of the License at:
      8  *
      9  *  http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  *
     17  ******************************************************************************/
     18 
     19 #include <string.h>
     20 #include "nfc_hal_int.h"
     21 #include "userial.h"
     22 
     23 /*****************************************************************************
     24 * Definitions
     25 *****************************************************************************/
     26 
     27 /* Internal flags */
     28 #define NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF  0x01    /* Application provided patchram in a single buffer */
     29 #define NFC_HAL_PRM_FLAGS_RFU               0x02    /* Reserved for future use */
     30 #define NFC_HAL_PRM_FLAGS_SIGNATURE_SENT    0x04    /* Signature sent to NFCC */
     31 #define NFC_HAL_PRM_FLAGS_I2C_FIX_REQUIRED  0x08    /* PreI2C patch required */
     32 #define NFC_HAL_PRM_FLAGS_BCM20791B3        0x10    /* B3 Patch (no RESET_NTF after patch download) */
     33 #define NFC_HAL_PRM_FLAGS_RM_RF             0x20    /* Erase Personality data */
     34 
     35 /* Secure patch download definitions */
     36 #define NFC_HAL_PRM_NCD_PATCHFILE_HDR_LEN  7       /* PRJID + MAJORVER + MINORVER + COUNT */
     37 
     38 /* Enumeration of power modes IDs */
     39 #define NFC_HAL_PRM_SPD_POWER_MODE_LPM     0
     40 #define NFC_HAL_PRM_SPD_POWER_MODE_FPM     1
     41 
     42 /* Version string for BCM20791B3 */
     43 const UINT8 NFC_HAL_PRM_BCM20791B3_STR[]   = "20791B3";
     44 #define NFC_HAL_PRM_BCM20791B3_STR_LEN     (sizeof (NFC_HAL_PRM_BCM20791B3_STR)-1)
     45 
     46 #define NFC_HAL_PRM_SPD_TOUT                   (6000)  /* timeout for SPD events (in ms)   */
     47 #define NFC_HAL_PRM_END_DELAY                  (250)   /* delay before sending any new command (ms)*/
     48 
     49 #if (NFC_HAL_PRM_DEBUG == TRUE)
     50 #define NFC_HAL_PRM_STATE(str)  HAL_TRACE_DEBUG2 ("%s st: %d", str, nfc_hal_cb.prm.state)
     51 #else
     52 #define NFC_HAL_PRM_STATE(str)
     53 #endif
     54 
     55 void nfc_hal_prm_post_baud_update (tHAL_NFC_STATUS status);
     56 typedef struct
     57 {
     58     UINT16              offset;
     59     UINT8               len;
     60 } tNFC_HAL_PRM_RM_RF;
     61 
     62 const tNFC_HAL_PRM_RM_RF nfc_hal_prm_rm_rf_20795a1 [] =
     63 {
     64     {0x0000,    0xFB},
     65     {0x019C,    0x08},
     66     {0x05E8,    0xFB},
     67     {0,         0}
     68 };
     69 static BOOLEAN nfc_hal_prm_nvm_rw_cmd(void);
     70 
     71 /*****************************************************************************
     72 ** Extern variable from nfc_hal_dm_cfg.c
     73 *****************************************************************************/
     74 extern tNFC_HAL_CFG *p_nfc_hal_cfg;
     75 
     76 /*******************************************************************************
     77 **
     78 ** Function         nfc_hal_prm_spd_handle_download_complete
     79 **
     80 ** Description      Patch download complete (for secure patch download)
     81 **
     82 ** Returns          void
     83 **
     84 *******************************************************************************/
     85 void nfc_hal_prm_spd_handle_download_complete (UINT8 event)
     86 {
     87     nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_IDLE;
     88 
     89     /* Notify application now */
     90     if (nfc_hal_cb.prm.p_cback)
     91         (nfc_hal_cb.prm.p_cback) (event);
     92 }
     93 
     94 /*******************************************************************************
     95 **
     96 ** Function         nfc_hal_prm_spd_send_next_segment
     97 **
     98 ** Description      Send next patch segment (for secure patch download)
     99 **
    100 ** Returns          void
    101 **
    102 *******************************************************************************/
    103 void nfc_hal_prm_spd_send_next_segment (void)
    104 {
    105     UINT8   *p_src;
    106     UINT16  len, offset = nfc_hal_cb.prm.cur_patch_offset;
    107     UINT8   hcit, oid, hdr0, type;
    108     UINT8   chipverlen;
    109     UINT8   chipverstr[NCI_SPD_HEADER_CHIPVER_LEN];
    110     UINT8   patch_hdr_size = NCI_MSG_HDR_SIZE + 1; /* 1 is for HCIT */
    111 
    112     /* Validate that segment is at least big enought to have NCI_MSG_HDR_SIZE + 1 (hcit) */
    113     if (nfc_hal_cb.prm.cur_patch_len_remaining < patch_hdr_size)
    114     {
    115         HAL_TRACE_ERROR0 ("Unexpected end of patch.");
    116         nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT);
    117         return;
    118     }
    119 
    120     /* Parse NCI command header */
    121     p_src = (UINT8*) (nfc_hal_cb.prm.p_cur_patch_data + offset);
    122     STREAM_TO_UINT8 (hcit, p_src);
    123     STREAM_TO_UINT8 (hdr0, p_src);
    124     STREAM_TO_UINT8 (oid,  p_src);
    125     STREAM_TO_UINT8 (len,  p_src);
    126     STREAM_TO_UINT8 (type, p_src);
    127 
    128 
    129     /* Update number of bytes comsumed */
    130     nfc_hal_cb.prm.cur_patch_offset += (len + patch_hdr_size);
    131     nfc_hal_cb.prm.cur_patch_len_remaining -=  (len + patch_hdr_size);
    132 
    133     /* Check if sending signature byte */
    134     if (  (oid == NCI_MSG_SECURE_PATCH_DOWNLOAD )
    135         &&(type == NCI_SPD_TYPE_SIGNATURE)  )
    136     {
    137         nfc_hal_cb.prm.flags |= NFC_HAL_PRM_FLAGS_SIGNATURE_SENT;
    138     }
    139     /* Check for header */
    140     else if (  (oid == NCI_MSG_SECURE_PATCH_DOWNLOAD )
    141              &&(type == NCI_SPD_TYPE_HEADER)  )
    142     {
    143         /* Check if patch is for BCM20791B3 */
    144         p_src += NCI_SPD_HEADER_OFFSET_CHIPVERLEN;
    145         STREAM_TO_UINT8 (chipverlen, p_src);
    146         if (memcmp (nfc_hal_cb.nvm_cb.chip_ver, p_src, chipverlen) != 0)
    147         {
    148             HAL_TRACE_ERROR0 ("Unexpected chip ver.");
    149             nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT);
    150             return;
    151         }
    152         STREAM_TO_ARRAY (chipverstr, p_src, NCI_SPD_HEADER_CHIPVER_LEN);
    153 
    154         if (memcmp (NFC_HAL_PRM_BCM20791B3_STR, chipverstr, NFC_HAL_PRM_BCM20791B3_STR_LEN) == 0)
    155         {
    156             /* Patch is for BCM2079B3 - do not wait for RESET_NTF after patch download */
    157             nfc_hal_cb.prm.flags |= NFC_HAL_PRM_FLAGS_BCM20791B3;
    158         }
    159         else
    160         {
    161             /* Patch is for BCM2079B4 or newer - wait for RESET_NTF after patch download */
    162             nfc_hal_cb.prm.flags &= ~NFC_HAL_PRM_FLAGS_BCM20791B3;
    163         }
    164     }
    165 
    166     /* Send the command (not including HCIT here) */
    167     nfc_hal_dm_send_nci_cmd ((UINT8*) (nfc_hal_cb.prm.p_cur_patch_data + offset + 1), (UINT8) (len + NCI_MSG_HDR_SIZE),
    168                              nfc_hal_prm_nci_command_complete_cback);
    169 }
    170 
    171 /*******************************************************************************
    172 **
    173 ** Function         nfc_hal_prm_spd_handle_next_patch_start
    174 **
    175 ** Description      Handle start of next patch (for secure patch download)
    176 **
    177 ** Returns          void
    178 **
    179 *******************************************************************************/
    180 void nfc_hal_prm_spd_handle_next_patch_start (void)
    181 {
    182     UINT32  cur_patch_mask;
    183     UINT32  cur_patch_len;
    184     BOOLEAN found_patch_to_download = FALSE;
    185 
    186     while (!found_patch_to_download)
    187     {
    188         /* Get length of current patch */
    189         cur_patch_len = nfc_hal_cb.prm.spd_patch_desc[nfc_hal_cb.prm.spd_cur_patch_idx].len;
    190 
    191         /* Check if this is a patch we need to download */
    192         cur_patch_mask = ((UINT32) 1 << nfc_hal_cb.prm.spd_patch_desc[nfc_hal_cb.prm.spd_cur_patch_idx].power_mode);
    193         if (nfc_hal_cb.prm.spd_patch_needed_mask & cur_patch_mask)
    194         {
    195             found_patch_to_download = TRUE;
    196         }
    197         else
    198         {
    199             /* Do not need to download this patch. Skip to next patch */
    200             HAL_TRACE_DEBUG1 ("Skipping patch for power_mode %i.", nfc_hal_cb.prm.spd_patch_desc[nfc_hal_cb.prm.spd_cur_patch_idx].power_mode);
    201 
    202             nfc_hal_cb.prm.spd_cur_patch_idx++;
    203             if (nfc_hal_cb.prm.spd_cur_patch_idx >= nfc_hal_cb.prm.spd_patch_count)
    204             {
    205                 /* No more to download */
    206                 nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_COMPLETE_EVT);
    207                 return;
    208             }
    209             else if (!(nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF))
    210             {
    211                 /* Notify adaptation layer to call HAL_NfcPrmDownloadContinue with the next patch header */
    212                 (nfc_hal_cb.prm.p_cback) (NFC_HAL_PRM_SPD_GET_NEXT_PATCH);
    213                 return;
    214             }
    215             else
    216             {
    217                 /* Patch in buffer. Skip over current patch. Check next patch */
    218                 nfc_hal_cb.prm.cur_patch_len_remaining -= (UINT16) cur_patch_len;
    219                 nfc_hal_cb.prm.cur_patch_offset += (UINT16) cur_patch_len;
    220             }
    221         }
    222     }
    223 
    224 
    225     /* Begin downloading patch */
    226     HAL_TRACE_DEBUG1 ("Downloading patch for power_mode %i.", nfc_hal_cb.prm.spd_patch_desc[nfc_hal_cb.prm.spd_cur_patch_idx].power_mode);
    227     nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_DOWNLOADING;
    228     nfc_hal_prm_spd_send_next_segment ();
    229 }
    230 
    231 #if (defined (NFC_HAL_PRE_I2C_PATCH_INCLUDED) && (NFC_HAL_PRE_I2C_PATCH_INCLUDED == TRUE))
    232 /*******************************************************************************
    233 **
    234 ** Function         nfc_hal_prm_spd_download_i2c_fix
    235 **
    236 ** Description      Start downloading patch for i2c fix
    237 **
    238 ** Returns          void
    239 **
    240 *******************************************************************************/
    241 void nfc_hal_prm_spd_download_i2c_fix (void)
    242 {
    243     UINT8 *p, *p_start;
    244     UINT16 patchfile_project_id;
    245     UINT16 patchfile_ver_major;
    246     UINT16 patchfile_ver_minor;
    247     UINT16 patchfile_patchsize;
    248     UINT8 u8;
    249 
    250     HAL_TRACE_DEBUG0 ("Downloading I2C fix...");
    251 
    252     /* Save pointer and offset of patchfile, so we can resume after downloading the i2c fix */
    253     nfc_hal_cb.prm.spd_patch_offset = nfc_hal_cb.prm.cur_patch_offset;
    254     nfc_hal_cb.prm.spd_patch_len_remaining = nfc_hal_cb.prm.cur_patch_len_remaining;
    255 
    256     /* Initialize pointers for downloading i2c fix */
    257     nfc_hal_cb.prm.p_cur_patch_data = nfc_hal_cb.prm_i2c.p_patch;
    258     nfc_hal_cb.prm.cur_patch_offset = 0;
    259     nfc_hal_cb.prm.cur_patch_len_remaining = nfc_hal_cb.prm_i2c.len;
    260 
    261     /* Parse the i2c patchfile */
    262     if (nfc_hal_cb.prm.cur_patch_len_remaining >= NFC_HAL_PRM_NCD_PATCHFILE_HDR_LEN)
    263     {
    264         /* Parse patchfile header */
    265         p = (UINT8 *) nfc_hal_cb.prm.p_cur_patch_data;
    266         p_start = p;
    267         STREAM_TO_UINT16 (patchfile_project_id, p);
    268         STREAM_TO_UINT16 (patchfile_ver_major, p);
    269         STREAM_TO_UINT16 (patchfile_ver_minor, p);
    270 
    271         /* RFU */
    272         p++;
    273 
    274         /* Check how many patches are in the patch file */
    275         STREAM_TO_UINT8 (u8, p);
    276 
    277         /* Should only be one patch */
    278         if (u8 > 1)
    279         {
    280             HAL_TRACE_ERROR1 ("Invalid i2c fix: invalid number of patches (%i)", u8);
    281             nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT);
    282             return;
    283         }
    284 
    285 
    286         /* Get info about the i2c patch*/
    287         STREAM_TO_UINT8 (u8, p);                     /* power mode (not needed for i2c patch)    */
    288         STREAM_TO_UINT16 (patchfile_patchsize, p);   /* size of patch                            */
    289 
    290         /* 5 byte RFU */
    291         p += 5;
    292 
    293         /* Adjust length to exclude patchfiloe header */
    294         nfc_hal_cb.prm.cur_patch_len_remaining -= (UINT16) (p - p_start);       /* Adjust size of patchfile                        */
    295         nfc_hal_cb.prm.cur_patch_offset += (UINT16) (p - p_start);              /* Bytes of patchfile transmitted/processed so far */
    296 
    297         /* Begin sending patch to the NFCC */
    298         nfc_hal_prm_spd_send_next_segment ();
    299     }
    300     else
    301     {
    302         /* ERROR: Bad length for patchfile */
    303         HAL_TRACE_ERROR0 ("Invalid i2c fix: unexpected end of patch");
    304         nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT);
    305     }
    306 }
    307 #endif /* NFC_HAL_PRE_I2C_PATCH_INCLUDED */
    308 
    309 /*******************************************************************************
    310 **
    311 ** Function         nfc_hal_prm_spd_check_version_continue
    312 **
    313 ** Description      Check patchfile version with current downloaded version
    314 **
    315 ** Returns          void
    316 **
    317 *******************************************************************************/
    318 static void nfc_hal_prm_spd_check_version_continue (void)
    319 {
    320     HAL_TRACE_DEBUG1 ("nfc_hal_prm_spd_check_version_continue 0x%02x", nfc_hal_cb.prm.flags);
    321     if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_RM_RF)
    322     {
    323         HAL_TRACE_DEBUG0("erase relevant blocks in NVM");
    324         nfc_hal_cb.prm.flags &= ~NFC_HAL_PRM_FLAGS_RM_RF;
    325         if (!nfc_hal_prm_nvm_rw_cmd())
    326         {
    327             /* nvm rw started successfully */
    328             return;
    329         }
    330     }
    331 #if (defined (NFC_HAL_PRE_I2C_PATCH_INCLUDED) && (NFC_HAL_PRE_I2C_PATCH_INCLUDED == TRUE))
    332     if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_I2C_FIX_REQUIRED)
    333     {
    334         HAL_TRACE_DEBUG0 ("I2C patch fix required.");
    335         /* Download i2c fix first */
    336         nfc_hal_prm_spd_download_i2c_fix ();
    337         return;
    338     }
    339 #endif  /* NFC_HAL_PRE_I2C_PATCH_INCLUDED */
    340 
    341     /* Download first segment */
    342     nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER;
    343     if (!(nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF))
    344     {
    345         /* Notify adaptation layer to call HAL_NfcPrmDownloadContinue with the next patch segment */
    346         (nfc_hal_cb.prm.p_cback) (NFC_HAL_PRM_SPD_GET_NEXT_PATCH);
    347     }
    348     else
    349     {
    350         nfc_hal_prm_spd_handle_next_patch_start ();
    351     }
    352 }
    353 
    354 /*******************************************************************************
    355 **
    356 ** Function         nfc_hal_prm_spd_check_version
    357 **
    358 ** Description      Check patchfile version with current downloaded version
    359 **
    360 ** Returns          void
    361 **
    362 *******************************************************************************/
    363 void nfc_hal_prm_spd_check_version (void)
    364 {
    365     UINT8 *p, *p_start, i;
    366     UINT32 nvm_patch_present_mask = 0;
    367     UINT32 patchfile_patch_present_mask;
    368     UINT16 patchfile_project_id = 0;
    369     UINT16 patchfile_ver_major = 0;
    370     UINT16 patchfile_ver_minor = 0;
    371     UINT16 patchfile_patchsize;
    372 
    373     UINT8  return_code = NFC_HAL_PRM_COMPLETE_EVT;
    374 
    375     /* Initialize patchfile offset pointers */
    376     p = p_start = NULL;
    377     patchfile_patchsize = 0;
    378 
    379     /* the good patches in NVM */
    380     if (nfc_hal_cb.nvm_cb.lpm_size && !(nfc_hal_cb.nvm_cb.flags & (NFC_HAL_NVM_FLAGS_LPM_BAD)))
    381         nvm_patch_present_mask  |= (1 << NFC_HAL_PRM_SPD_POWER_MODE_LPM);
    382 
    383     if (nfc_hal_cb.nvm_cb.fpm_size && !(nfc_hal_cb.nvm_cb.flags & (NFC_HAL_NVM_FLAGS_FPM_BAD)))
    384         nvm_patch_present_mask  |= (1 << NFC_HAL_PRM_SPD_POWER_MODE_FPM);
    385 
    386     /* Get patchfile version */
    387     if (nfc_hal_cb.prm.cur_patch_len_remaining >= NFC_HAL_PRM_NCD_PATCHFILE_HDR_LEN)
    388     {
    389         /* Parse patchfile header */
    390         p       = (UINT8 *) nfc_hal_cb.prm.p_cur_patch_data;
    391         p_start = p;
    392         STREAM_TO_UINT16 (patchfile_project_id, p);
    393         STREAM_TO_UINT16 (patchfile_ver_major, p);
    394         STREAM_TO_UINT16 (patchfile_ver_minor, p);
    395 
    396         /* RFU */
    397         p++;
    398 
    399         /* Check how many patches are in the patch file */
    400         STREAM_TO_UINT8 (nfc_hal_cb.prm.spd_patch_count, p);
    401 
    402         if (nfc_hal_cb.prm.spd_patch_count > NFC_HAL_PRM_MAX_PATCH_COUNT)
    403         {
    404             HAL_TRACE_ERROR2 ("Unsupported patchfile (number of patches (%i) exceeds maximum (%i)",
    405                                nfc_hal_cb.prm.spd_patch_count, NFC_HAL_PRM_MAX_PATCH_COUNT);
    406         }
    407 
    408         /* Mask of patches that are present in the patchfile */
    409         patchfile_patch_present_mask = 0;
    410 
    411         /* Get lengths for each patch */
    412         for (i = 0; i < nfc_hal_cb.prm.spd_patch_count; i++)
    413         {
    414             /* Get power mode for this patch */
    415             STREAM_TO_UINT8 (nfc_hal_cb.prm.spd_patch_desc[i].power_mode, p);
    416 
    417             /* Update mask of power-modes present in the patchfile */
    418             patchfile_patch_present_mask |= ((UINT32) 1 << nfc_hal_cb.prm.spd_patch_desc[i].power_mode);
    419 
    420             /* Get length of patch */
    421             STREAM_TO_UINT16 (nfc_hal_cb.prm.spd_patch_desc[i].len, p);
    422 
    423             /* Add total size of patches */
    424             patchfile_patchsize += nfc_hal_cb.prm.spd_patch_desc[i].len;
    425 
    426             /* 5 byte RFU */
    427             p += 5;
    428         }
    429 
    430         /* Adjust offset to after the patch file header */
    431         nfc_hal_cb.prm.cur_patch_offset += (UINT16) (p - p_start);              /* Bytes of patchfile transmitted/processed so far */
    432         nfc_hal_cb.prm.cur_patch_len_remaining -= (UINT16) (p - p_start);       /* Adjust size of patchfile                        */
    433 
    434 
    435         HAL_TRACE_DEBUG4 ("NVM Patch info: flags=0x%04x,   Ver=%i.%i, PatchMask=0x%08x",
    436             nfc_hal_cb.nvm_cb.flags, nfc_hal_cb.nvm_cb.ver_major, nfc_hal_cb.nvm_cb.ver_minor, nvm_patch_present_mask );
    437         HAL_TRACE_DEBUG6 ("Patchfile info: ProjID=0x%04x,  Ver=%i.%i, Num patches=%i, PatchMask=0x%08x, PatchSize=%i",
    438                            patchfile_project_id, patchfile_ver_major, patchfile_ver_minor,
    439                            nfc_hal_cb.prm.spd_patch_count, patchfile_patch_present_mask, patchfile_patchsize);
    440 
    441         /*********************************************************************
    442         * Version check of patchfile against NVM
    443         *********************************************************************/
    444         /* Download the patchfile if no patches in NVM */
    445         if ((nfc_hal_cb.nvm_cb.project_id == 0) || !(nfc_hal_cb.nvm_cb.flags & NFC_HAL_NVM_FLAGS_PATCH_PRESENT))
    446         {
    447             /* No patch in NVM, need to download all */
    448             nfc_hal_cb.prm.spd_patch_needed_mask = patchfile_patch_present_mask;
    449             if (nfc_hal_cb.dev_cb.brcm_hw_id == BRCM_20795A1_ID)
    450             {
    451                 nfc_hal_cb.prm.flags   |= NFC_HAL_PRM_FLAGS_RM_RF;
    452                 nfc_hal_cb.prm.p_param  = (void *)nfc_hal_prm_rm_rf_20795a1;
    453                 nfc_hal_cb.prm.param_idx = 0;
    454             }
    455 
    456             HAL_TRACE_DEBUG2 ("No previous patch detected. Downloading patch %i.%i",
    457                               patchfile_ver_major, patchfile_ver_minor);
    458         }
    459         /* Skip download if project ID of patchfile does not match NVM */
    460         else if (nfc_hal_cb.nvm_cb.project_id != patchfile_project_id)
    461         {
    462             /* Project IDs mismatch */
    463             HAL_TRACE_DEBUG2 ("Patch download skipped: Mismatched Project ID (NVM ProjId: 0x%04x, Patchfile ProjId: 0x%04x)",
    464                               nfc_hal_cb.nvm_cb.project_id, patchfile_project_id);
    465 
    466             return_code = NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT;
    467         }
    468         /* Skip download if version of patchfile is equal to version in NVM */
    469         /*                  and patches of the power modes are the same as the good patches in NVM */
    470         else if (  (nfc_hal_cb.nvm_cb.ver_major == patchfile_ver_major)
    471             &&(nfc_hal_cb.nvm_cb.ver_minor == patchfile_ver_minor)
    472                  &&((nvm_patch_present_mask | patchfile_patch_present_mask) == nvm_patch_present_mask)  ) /* if the NVM patch include all the patched in file */
    473         {
    474             HAL_TRACE_DEBUG2 ("Patch download skipped. NVM patch (version %i.%i) is the same than the patchfile ",
    475                               nfc_hal_cb.nvm_cb.ver_major, nfc_hal_cb.nvm_cb.ver_minor);
    476 
    477             return_code = NFC_HAL_PRM_COMPLETE_EVT;
    478         }
    479         /* Remaining cases: Download all patches in the patchfile */
    480         else
    481         {
    482             nfc_hal_cb.prm.spd_patch_needed_mask = patchfile_patch_present_mask;
    483 
    484             HAL_TRACE_DEBUG4 ("Downloading patch version: %i.%i (previous version in NVM: %i.%i)...",
    485                               patchfile_ver_major, patchfile_ver_minor,
    486                               nfc_hal_cb.nvm_cb.ver_major, nfc_hal_cb.nvm_cb.ver_minor);
    487         }
    488 
    489     }
    490     else
    491     {
    492         /* Invalid patch file header */
    493         HAL_TRACE_ERROR0 ("Invalid patch file header.");
    494 
    495         return_code = NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT;
    496     }
    497 
    498     /* If we need to download anything, get the first patch to download */
    499     if (nfc_hal_cb.prm.spd_patch_needed_mask)
    500     {
    501         HAL_TRACE_ERROR4 ("Downloading patch version: %i.%i (previous version in NVM: %i.%i)...",
    502                             patchfile_ver_major, patchfile_ver_minor,
    503                             nfc_hal_cb.nvm_cb.ver_major, nfc_hal_cb.nvm_cb.ver_minor);
    504 #if (defined (NFC_HAL_PRE_I2C_PATCH_INCLUDED) && (NFC_HAL_PRE_I2C_PATCH_INCLUDED == TRUE))
    505         /* Check if I2C patch is needed: if                                     */
    506         /*      - I2C patch file was provided using HAL_NfcPrmSetI2cPatch, and        */
    507         /*      -   current patch in NVM has ProjectID=0, or                    */
    508         /*          FPM is not present or corrupted, or                         */
    509         /*          or patchfile is major-ver 76+                               */
    510         /*          or patchfile is not for B3 (always download for B4 onward)  */
    511         if (  (nfc_hal_cb.prm_i2c.p_patch)
    512             &&(  (nfc_hal_cb.nvm_cb.project_id == 0)
    513                ||(nfc_hal_cb.nvm_cb.fpm_size == 0)
    514                ||(nfc_hal_cb.nvm_cb.flags & NFC_HAL_NVM_FLAGS_FPM_BAD)
    515                ||(patchfile_ver_major >= 76)
    516                ||(!(nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_BCM20791B3)) ))
    517         {
    518             HAL_TRACE_DEBUG0 ("I2C patch fix required.");
    519             nfc_hal_cb.prm.flags |= NFC_HAL_PRM_FLAGS_I2C_FIX_REQUIRED;
    520         }
    521 #endif  /* NFC_HAL_PRE_I2C_PATCH_INCLUDED */
    522         nfc_hal_prm_spd_check_version_continue ();
    523     }
    524     else
    525     {
    526         static BOOLEAN firstTime = TRUE;
    527         if (firstTime)
    528         {
    529             HAL_TRACE_ERROR2 ("NVM patch version is %d.%d",
    530                               nfc_hal_cb.nvm_cb.ver_major, nfc_hal_cb.nvm_cb.ver_minor);
    531             firstTime = FALSE;
    532         }
    533         /* Download complete */
    534         nfc_hal_prm_spd_handle_download_complete (return_code);
    535     }
    536 }
    537 
    538 #if (NFC_HAL_TRACE_VERBOSE == TRUE)
    539 /*******************************************************************************
    540 **
    541 ** Function         nfc_hal_prm_spd_status_str
    542 **
    543 ** Description      Return status string for a given spd status code
    544 **
    545 ** Returns          Status string
    546 **
    547 *******************************************************************************/
    548 UINT8 *nfc_hal_prm_spd_status_str (UINT8 spd_status_code)
    549 {
    550     char *p_str;
    551 
    552     switch (spd_status_code)
    553     {
    554     case NCI_STATUS_SPD_ERROR_DEST:
    555         p_str = "SPD_ERROR_DEST";
    556         break;
    557 
    558     case NCI_STATUS_SPD_ERROR_PROJECTID:
    559         p_str = "SPD_ERROR_PROJECTID";
    560         break;
    561 
    562     case NCI_STATUS_SPD_ERROR_CHIPVER:
    563         p_str = "SPD_ERROR_CHIPVER";
    564         break;
    565 
    566     case NCI_STATUS_SPD_ERROR_MAJORVER:
    567         p_str = "SPD_ERROR_MAJORVER";
    568         break;
    569 
    570     case NCI_STATUS_SPD_ERROR_INVALID_PARAM:
    571         p_str = "SPD_ERROR_INVALID_PARAM";
    572         break;
    573 
    574     case NCI_STATUS_SPD_ERROR_INVALID_SIG:
    575         p_str = "SPD_ERROR_INVALID_SIG";
    576         break;
    577 
    578     case NCI_STATUS_SPD_ERROR_NVM_CORRUPTED:
    579         p_str = "SPD_ERROR_NVM_CORRUPTED";
    580         break;
    581 
    582     case NCI_STATUS_SPD_ERROR_PWR_MODE:
    583         p_str = "SPD_ERROR_PWR_MODE";
    584         break;
    585 
    586     case NCI_STATUS_SPD_ERROR_MSG_LEN:
    587         p_str = "SPD_ERROR_MSG_LEN";
    588         break;
    589 
    590     case NCI_STATUS_SPD_ERROR_PATCHSIZE:
    591         p_str = "SPD_ERROR_PATCHSIZE";
    592         break;
    593 
    594     default:
    595         p_str = "Unspecified Error";
    596         break;
    597 
    598     }
    599 
    600     return ((UINT8*) p_str);
    601 }
    602 #endif  /* (NFC_HAL_TRACE_VERBOSE == TRUE) */
    603 /*******************************************************************************
    604 **
    605 ** Function         nfc_hal_prm_nvm_rw_cmd
    606 **
    607 ** Description      Non Volatile Read Write Command; for now only write zeros
    608 **
    609 ** Returns          TRUE if done.
    610 **
    611 *******************************************************************************/
    612 static BOOLEAN nfc_hal_prm_nvm_rw_cmd(void)
    613 {
    614     tNFC_HAL_PRM_RM_RF  *p_param = (tNFC_HAL_PRM_RM_RF *)(nfc_hal_cb.prm.p_param);
    615     UINT8   *p_buff, *p, *p_end;
    616     UINT8   len = 0;
    617     UINT16  cmd_len;
    618 
    619     if (p_param)
    620         len     = p_param[nfc_hal_cb.prm.param_idx].len;
    621     HAL_TRACE_DEBUG2 ("nfc_hal_prm_nvm_rw_cmd: %d/%d", nfc_hal_cb.prm.param_idx, len);
    622     if (len == 0)
    623     {
    624         return TRUE;
    625     }
    626     cmd_len = len + 7;
    627 
    628     if ((p_buff = (UINT8 *) GKI_getbuf(cmd_len)) == NULL)
    629     {
    630         HAL_TRACE_ERROR0 ("NVM No buffer");
    631         nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_EVT);
    632         return TRUE;
    633     }
    634 
    635     p = p_buff;
    636 
    637     UINT8_TO_STREAM  (p, (NCI_MTS_CMD|NCI_GID_PROP));
    638     UINT8_TO_STREAM  (p, NCI_MSG_EEPROM_RW);
    639     UINT8_TO_STREAM  (p, (len+4));
    640     UINT8_TO_STREAM  (p, 1); /* 1=write 0=read */
    641     UINT16_TO_STREAM  (p, p_param[nfc_hal_cb.prm.param_idx].offset);
    642     UINT8_TO_STREAM  (p, len);
    643     memset (p, 0, len); /* Fill remaining bytes with zeros*/
    644 
    645     nfc_hal_cb.prm.param_idx++;
    646     nfc_hal_dm_send_nci_cmd(p_buff, cmd_len, nfc_hal_prm_nci_command_complete_cback);
    647     GKI_freebuf (p_buff);
    648     return FALSE;
    649 }
    650 
    651 /*******************************************************************************
    652 **
    653 ** Function         nfc_hal_prm_nci_command_complete_cback
    654 **
    655 ** Description      Callback for NCI vendor specific command complete
    656 **                  (for secure patch download)
    657 **
    658 ** Returns          void
    659 **
    660 *******************************************************************************/
    661 void nfc_hal_prm_nci_command_complete_cback (tNFC_HAL_NCI_EVT event, UINT16 data_len, UINT8 *p_data)
    662 {
    663     UINT8 status, u8;
    664     UINT8 *p;
    665     UINT32 post_signature_delay;
    666 
    667     NFC_HAL_PRM_STATE ("nfc_hal_prm_nci_command_complete_cback");
    668 
    669     /* Stop the command-timeout timer */
    670     nfc_hal_main_stop_quick_timer (&nfc_hal_cb.prm.timer);
    671 
    672     /* Skip over NCI header */
    673     p = p_data + NCI_MSG_HDR_SIZE;
    674 
    675     /* Handle SECURE_PATCH_DOWNLOAD Rsp */
    676     if (event == NFC_VS_SEC_PATCH_DOWNLOAD_EVT)
    677     {
    678         /* Status and error code */
    679         STREAM_TO_UINT8 (status, p);
    680         STREAM_TO_UINT8 (u8, p);
    681 
    682         if (status != NCI_STATUS_OK)
    683         {
    684 #if (NFC_HAL_TRACE_VERBOSE == TRUE)
    685             HAL_TRACE_ERROR2 ("Patch download failed, reason code=0x%X (%s)", status, nfc_hal_prm_spd_status_str (status));
    686 #else
    687             HAL_TRACE_ERROR1 ("Patch download failed, reason code=0x%X", status);
    688 #endif
    689 
    690             /* Notify application */
    691             nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT);
    692             return;
    693         }
    694 
    695         /* If last segment (SIGNATURE) sent */
    696         if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_SIGNATURE_SENT)
    697         {
    698             /* Wait for authentication complete (SECURE_PATCH_DOWNLOAD NTF), including time to commit to NVM (for BCM43341B0) */
    699             nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_AUTHENTICATING;
    700             nfc_hal_main_start_quick_timer (&nfc_hal_cb.prm.timer, 0x00,
    701                                             (NFC_HAL_PRM_COMMIT_DELAY * QUICK_TIMER_TICKS_PER_SEC) / 1000);
    702             return;
    703         }
    704         /* Download next segment */
    705         else if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF)
    706         {
    707             /* If patch is in a buffer, get next patch from buffer */
    708             nfc_hal_prm_spd_send_next_segment ();
    709         }
    710         else
    711         {
    712             /* Notify adaptation layer to get next patch segment (via HAL_NfcPrmDownloadContinue) */
    713             (nfc_hal_cb.prm.p_cback) (NFC_HAL_PRM_CONTINUE_EVT);
    714         }
    715     }
    716     /* Handle SECURE_PATCH_DOWNLOAD NTF */
    717     else if (event == NFC_VS_SEC_PATCH_AUTH_EVT)
    718     {
    719         HAL_TRACE_DEBUG1 ("prm flags:0x%x.", nfc_hal_cb.prm.flags);
    720         /* Status and error code */
    721         STREAM_TO_UINT8 (status, p);
    722         STREAM_TO_UINT8 (u8, p);
    723 
    724         /* Sanity check - should only get this NTF while in AUTHENTICATING stage */
    725         if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_AUTHENTICATING)
    726         {
    727             if (status != NCI_STATUS_OK)
    728             {
    729                 HAL_TRACE_ERROR0 ("Patch authentication failed");
    730                 nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_BAD_SIGNATURE_EVT);
    731                 return;
    732             }
    733 
    734 #if (defined (NFC_HAL_PRE_I2C_PATCH_INCLUDED) && (NFC_HAL_PRE_I2C_PATCH_INCLUDED == TRUE))
    735             if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_I2C_FIX_REQUIRED)
    736             {
    737                 HAL_TRACE_DEBUG1 ("PreI2C patch downloaded...waiting %i ms for NFCC to reboot.", nfc_hal_cb.prm_i2c.prei2c_delay);
    738 
    739                 /* Restore pointers to patchfile */
    740                 nfc_hal_cb.prm.flags &= ~NFC_HAL_PRM_FLAGS_I2C_FIX_REQUIRED;
    741                 nfc_hal_cb.prm.p_cur_patch_data = nfc_hal_cb.prm.p_spd_patch;
    742                 nfc_hal_cb.prm.cur_patch_offset = nfc_hal_cb.prm.spd_patch_offset;
    743                 nfc_hal_cb.prm.cur_patch_len_remaining = nfc_hal_cb.prm.spd_patch_len_remaining;
    744 
    745                 /* Resume normal patch download */
    746                 nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER;
    747                 nfc_hal_cb.prm.flags &= ~NFC_HAL_PRM_FLAGS_SIGNATURE_SENT;
    748 
    749                 /* Post PreI2C delay */
    750                 nfc_hal_main_start_quick_timer (&nfc_hal_cb.prm.timer, 0x00, (nfc_hal_cb.prm_i2c.prei2c_delay * QUICK_TIMER_TICKS_PER_SEC) / 1000);
    751 
    752                 return;
    753             }
    754 #endif  /* NFC_HAL_PRE_I2C_PATCH_INCLUDED */
    755 
    756 
    757             /* Wait for NFCC to save the patch to NVM */
    758             if (!(nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_BCM20791B3))
    759             {
    760                 /* 20791B4 or newer - wait for RESET_NTF; including time to commit to NVM (for BCM20791B4+) */
    761                 post_signature_delay = NFC_HAL_PRM_COMMIT_DELAY;
    762                 HAL_TRACE_DEBUG1 ("Patch downloaded and authenticated. Waiting %i ms for RESET NTF...", post_signature_delay);
    763 
    764             }
    765             else if (nfc_hal_cb.nvm_cb.flags & NFC_HAL_NVM_FLAGS_NO_NVM)
    766             {
    767                 /* No NVM. Wait for NFCC to restart */
    768                 post_signature_delay = NFC_HAL_PRM_END_DELAY;
    769                 HAL_TRACE_DEBUG1 ("Patch downloaded and authenticated. Waiting %i ms for NFCC to restart...", post_signature_delay);
    770             }
    771             else
    772             {
    773                 /* Wait for NFCC to save the patch to NVM (need about 1 ms per byte) */
    774                 post_signature_delay = nfc_hal_cb.prm.spd_patch_desc[nfc_hal_cb.prm.spd_cur_patch_idx].len;
    775                 if (post_signature_delay < nfc_hal_cb.prm.patchram_delay)
    776                     post_signature_delay = nfc_hal_cb.prm.patchram_delay;
    777                 HAL_TRACE_DEBUG1 ("Patch downloaded and authenticated. Waiting %i ms for NVM update to complete...", post_signature_delay);
    778             }
    779 
    780             nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_AUTH_DONE;
    781 
    782             nfc_hal_main_start_quick_timer (&nfc_hal_cb.prm.timer, 0x00,
    783                                             (post_signature_delay * QUICK_TIMER_TICKS_PER_SEC) / 1000);
    784         }
    785         else
    786         {
    787             HAL_TRACE_ERROR0 ("Got unexpected SECURE_PATCH_DOWNLOAD NTF");
    788             nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_EVT);
    789         }
    790     }
    791     /* Handle NCI_MSG_GET_PATCH_VERSION RSP */
    792     else if (event == NFC_VS_GET_PATCH_VERSION_EVT)
    793     {
    794         nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_COMPLETE_EVT);
    795     }
    796     else if (event == NFC_VS_EEPROM_RW_EVT)
    797     {
    798         STREAM_TO_UINT8 (status, p);
    799         if (status == NCI_STATUS_OK)
    800         {
    801             if (nfc_hal_prm_nvm_rw_cmd ())
    802             {
    803                 nfc_hal_prm_spd_check_version_continue ();
    804             }
    805         }
    806         else
    807         {
    808             HAL_TRACE_ERROR0 ("NVM failed");
    809             nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_EVT);
    810         }
    811     }
    812     else
    813     {
    814         /* Invalid response from NFCC during patch download */
    815         HAL_TRACE_ERROR1 ("Invalid response from NFCC during patch download (opcode=0x%02X)", event);
    816         nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT);
    817     }
    818 
    819     NFC_HAL_PRM_STATE ("prm_nci_command_complete_cback");
    820 }
    821 
    822 /*******************************************************************************
    823 **
    824 ** Function         nfc_hal_prm_nfcc_ready_to_continue
    825 **
    826 ** Description      Continue to download patch or notify application completition
    827 **
    828 ** Returns          void
    829 **
    830 *******************************************************************************/
    831 void nfc_hal_prm_nfcc_ready_to_continue (void)
    832 {
    833     UINT8 get_patch_version_cmd [NCI_MSG_HDR_SIZE] =
    834     {
    835         NCI_MTS_CMD|NCI_GID_PROP,
    836         NCI_MSG_GET_PATCH_VERSION,
    837         0x00
    838     };
    839 
    840     /* Clear the bit for the patch we just downloaded */
    841     nfc_hal_cb.prm.spd_patch_needed_mask &= ~ ((UINT32) 1 << nfc_hal_cb.prm.spd_patch_desc[nfc_hal_cb.prm.spd_cur_patch_idx].power_mode);
    842 
    843     /* Check if another patch to download */
    844     nfc_hal_cb.prm.spd_cur_patch_idx++;
    845     if ((nfc_hal_cb.prm.spd_patch_needed_mask) && (nfc_hal_cb.prm.spd_cur_patch_idx < nfc_hal_cb.prm.spd_patch_count))
    846     {
    847         nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER;
    848         nfc_hal_cb.prm.flags &= ~NFC_HAL_PRM_FLAGS_SIGNATURE_SENT;
    849 
    850         if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF)
    851         {
    852             /* If patch is in a buffer, get next patch from buffer */
    853             nfc_hal_prm_spd_handle_next_patch_start ();
    854         }
    855         else
    856         {
    857             /* Notify adaptation layer to get next patch header (via HAL_NfcPrmDownloadContinue) */
    858             (nfc_hal_cb.prm.p_cback) (NFC_HAL_PRM_SPD_GET_NEXT_PATCH);
    859         }
    860 
    861     }
    862     else
    863     {
    864         /* Done downloading */
    865         HAL_TRACE_DEBUG0 ("Patch downloaded and authenticated. Get new patch version.");
    866         /* add get patch info again to verify the effective FW version */
    867         nfc_hal_dm_send_nci_cmd (get_patch_version_cmd, NCI_MSG_HDR_SIZE, nfc_hal_prm_nci_command_complete_cback);
    868         nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_W4_GET_VERSION;
    869     }
    870 }
    871 
    872 /*******************************************************************************
    873 **
    874 ** Function         nfc_hal_prm_spd_reset_ntf
    875 **
    876 ** Description      Received RESET NTF from NFCC, indicating it has completed
    877 **                  reset after patch download.
    878 **
    879 ** Returns          void
    880 **
    881 *******************************************************************************/
    882 void nfc_hal_prm_spd_reset_ntf (UINT8 reset_reason, UINT8 reset_type)
    883 {
    884     /* Check if we were expecting a RESET NTF */
    885     if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_AUTH_DONE)
    886     {
    887         HAL_TRACE_DEBUG2 ("Received RESET NTF after patch download (reset_reason=%i, reset_type=%i)", reset_reason, reset_type);
    888 
    889         /* Stop waiting for RESET NTF */
    890         nfc_hal_main_stop_quick_timer (&nfc_hal_cb.prm.timer);
    891 
    892         {
    893             /* Continue with patch download */
    894             nfc_hal_prm_nfcc_ready_to_continue ();
    895         }
    896     }
    897     else if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER)
    898     {
    899         HAL_TRACE_DEBUG0 ("Received RESET NTF after pre-I2C patch download. Proceeding with patch download...");
    900 
    901         /* Stop waiting for RESET NTF */
    902         nfc_hal_main_stop_quick_timer (&nfc_hal_cb.prm.timer);
    903         nfc_hal_prm_spd_handle_next_patch_start ();
    904     }
    905     else
    906     {
    907         HAL_TRACE_ERROR2 ("Received unexpected RESET NTF (reset_reason=%i, reset_type=%i)", reset_reason, reset_type);
    908     }
    909 }
    910 
    911 /*******************************************************************************
    912 **
    913 ** Function:    nfc_post_final_baud_update
    914 **
    915 ** Description: Called after baud rate udate
    916 **
    917 ** Returns:     Nothing
    918 **
    919 *******************************************************************************/
    920 void nfc_hal_prm_post_baud_update (tHAL_NFC_STATUS status)
    921 {
    922     NFC_HAL_PRM_STATE ("nfc_hal_prm_post_baud_update");
    923 
    924     if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_AUTH_DONE)
    925     {
    926         /* Proceed with next step of patch download sequence */
    927         nfc_hal_prm_nfcc_ready_to_continue ();
    928     }
    929 }
    930 
    931 /*******************************************************************************
    932 **
    933 ** Function         nfc_hal_prm_process_timeout
    934 **
    935 ** Description      Process timer expireation for patch download
    936 **
    937 ** Returns          void
    938 **
    939 *******************************************************************************/
    940 void nfc_hal_prm_process_timeout (void *p_tle)
    941 {
    942     NFC_HAL_PRM_STATE ("nfc_hal_prm_process_timeout");
    943 
    944     if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_AUTH_DONE)
    945     {
    946         if (!(nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_BCM20791B3))
    947         {
    948             /* Timeout waiting for RESET NTF after signature sent */
    949             HAL_TRACE_ERROR0 ("Timeout waiting for RESET NTF after patch download");
    950             nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_EVT);
    951         }
    952         else
    953         {
    954             nfc_hal_prm_nfcc_ready_to_continue ();
    955         }
    956     }
    957     else if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER)
    958     {
    959         HAL_TRACE_DEBUG0 ("Delay after PreI2C patch download...proceeding to download firmware patch");
    960         nfc_hal_prm_spd_handle_next_patch_start ();
    961     }
    962     else if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_W4_GET_VERSION)
    963     {
    964         HAL_TRACE_DEBUG0 ("get patch version timeout???");
    965         nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_COMPLETE_EVT);
    966     }
    967     else
    968     {
    969         HAL_TRACE_ERROR1 ("Patch download: command timeout (state=%i)", nfc_hal_cb.prm.state);
    970 
    971         nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_EVT);
    972     }
    973 
    974     NFC_HAL_PRM_STATE ("nfc_hal_prm_process_timeout");
    975 }
    976 
    977 
    978 /*******************************************************************************
    979 **
    980 ** Function         HAL_NfcPrmDownloadStart
    981 **
    982 ** Description      Initiate patch download
    983 **
    984 ** Input Params
    985 **                  format_type     patch format type
    986 **                                  (NFC_HAL_PRM_FORMAT_BIN, NFC_HAL_PRM_FORMAT_HCD, or
    987 **                                   NFC_HAL_PRM_FORMAT_NCD)
    988 **
    989 **                  dest_address    destination adderess (needed for BIN format only)
    990 **
    991 **                  p_patchram_buf  pointer to patchram buffer. If NULL,
    992 **                                  then app must call HAL_NfcPrmDownloadContinue when
    993 **                                  NFC_HAL_PRM_CONTINUE_EVT is received, to send the next
    994 **                                  segment of patchram
    995 **
    996 **                  patchram_len    size of p_patchram_buf (if non-NULL)
    997 **
    998 **                  patchram_delay  The delay after each patch.
    999 **                                  If the given value is less than the size of the patchram,
   1000 **                                  the size of patchram is used instead.
   1001 **
   1002 **                  p_cback         callback for download status
   1003 **
   1004 **
   1005 ** Returns          TRUE if successful, otherwise FALSE
   1006 **
   1007 **
   1008 *******************************************************************************/
   1009 BOOLEAN HAL_NfcPrmDownloadStart (tNFC_HAL_PRM_FORMAT format_type,
   1010                                  UINT32              dest_address,
   1011                                  UINT8               *p_patchram_buf,
   1012                                  UINT32              patchram_len,
   1013                                  UINT32              patchram_delay,
   1014                                  tNFC_HAL_PRM_CBACK  *p_cback)
   1015 {
   1016     HAL_TRACE_API0 ("HAL_NfcPrmDownloadStart ()");
   1017 
   1018     memset (&nfc_hal_cb.prm, 0, sizeof (tNFC_HAL_PRM_CB));
   1019 
   1020     if (p_patchram_buf)
   1021     {
   1022         nfc_hal_cb.prm.p_cur_patch_data = p_patchram_buf;
   1023         nfc_hal_cb.prm.cur_patch_offset = 0;
   1024         nfc_hal_cb.prm.cur_patch_len_remaining = (UINT16) patchram_len;
   1025         nfc_hal_cb.prm.flags |= NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF;
   1026 
   1027         if (patchram_len == 0)
   1028             return FALSE;
   1029     }
   1030 
   1031     nfc_hal_cb.prm.p_cback          = p_cback;
   1032     nfc_hal_cb.prm.dest_ram         = dest_address;
   1033     nfc_hal_cb.prm.format           = format_type;
   1034     nfc_hal_cb.prm.patchram_delay   = patchram_delay;
   1035 
   1036     nfc_hal_cb.prm.timer.p_cback = nfc_hal_prm_process_timeout;
   1037 
   1038     if (format_type == NFC_HAL_PRM_FORMAT_NCD)
   1039     {
   1040         /* Store patch buffer pointer and length */
   1041         nfc_hal_cb.prm.p_spd_patch             = p_patchram_buf;
   1042         nfc_hal_cb.prm.spd_patch_len_remaining = (UINT16)patchram_len;
   1043         nfc_hal_cb.prm.spd_patch_offset        = 0;
   1044 
   1045         /* If patch download is required, but no NVM is available, then abort */
   1046         if ((p_nfc_hal_cfg->nfc_hal_prm_nvm_required) && (nfc_hal_cb.nvm_cb.flags & NFC_HAL_NVM_FLAGS_NO_NVM))
   1047         {
   1048             HAL_TRACE_ERROR0 ("This platform requires NVM and the NVM is not available - Abort");
   1049             nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_NO_NVM_EVT);
   1050             return FALSE;
   1051         }
   1052 
   1053         /* Compare patch version in NVM with version in patchfile */
   1054         nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_COMPARE_VERSION;
   1055         if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF)
   1056         {
   1057             /* If patchfile is in a buffer, get patch version from buffer */
   1058             nfc_hal_prm_spd_check_version ();
   1059         }
   1060         else
   1061         {
   1062             /* If patchfile is not in a buffer, then request patchfile header from adaptation layer. */
   1063             (nfc_hal_cb.prm.p_cback) (NFC_HAL_PRM_SPD_GET_PATCHFILE_HDR_EVT);
   1064         }
   1065     }
   1066     else
   1067     {
   1068         HAL_TRACE_ERROR0 ("Unexpected patch format.");
   1069         return FALSE;
   1070     }
   1071 
   1072     return TRUE;
   1073 }
   1074 
   1075 /*******************************************************************************
   1076 **
   1077 ** Function         HAL_NfcPrmDownloadContinue
   1078 **
   1079 ** Description      Send next segment of patchram to controller. Called when
   1080 **                  NFC_HAL_PRM_CONTINUE_EVT is received.
   1081 **
   1082 **                  Only needed if HAL_NfcPrmDownloadStart was called with
   1083 **                  p_patchram_buf=NULL
   1084 **
   1085 ** Input Params     p_patch_data    pointer to patch data
   1086 **                  patch_data_len  patch data len
   1087 **
   1088 ** Returns          TRUE if successful, otherwise FALSE
   1089 **
   1090 *******************************************************************************/
   1091 BOOLEAN HAL_NfcPrmDownloadContinue (UINT8 *p_patch_data,
   1092                                     UINT16 patch_data_len)
   1093 {
   1094     HAL_TRACE_API2 ("HAL_NfcPrmDownloadContinue ():state = %d, patch_data_len=%d",
   1095                      nfc_hal_cb.prm.state, patch_data_len);
   1096 
   1097     /* Check if we are in a valid state for this API */
   1098     if (  (nfc_hal_cb.prm.state != NFC_HAL_PRM_ST_SPD_COMPARE_VERSION)
   1099         &&(nfc_hal_cb.prm.state != NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER)
   1100         &&(nfc_hal_cb.prm.state != NFC_HAL_PRM_ST_SPD_DOWNLOADING)  )
   1101         return FALSE;
   1102 
   1103     if (patch_data_len == 0)
   1104         return FALSE;
   1105 
   1106     nfc_hal_cb.prm.cur_patch_offset = 0;
   1107     nfc_hal_cb.prm.p_cur_patch_data = p_patch_data;
   1108     nfc_hal_cb.prm.cur_patch_len_remaining = patch_data_len;
   1109 
   1110     /* Call appropriate handler */
   1111     if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_COMPARE_VERSION)
   1112     {
   1113         nfc_hal_prm_spd_check_version ();
   1114     }
   1115     else if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER)
   1116     {
   1117         nfc_hal_prm_spd_handle_next_patch_start ();
   1118     }
   1119     else if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_DOWNLOADING)
   1120     {
   1121         nfc_hal_prm_spd_send_next_segment ();
   1122     }
   1123     else
   1124     {
   1125         HAL_TRACE_ERROR1 ("Unexpected patch state:%d.", nfc_hal_cb.prm.state);
   1126     }
   1127 
   1128     return TRUE;
   1129 }
   1130 
   1131 /*******************************************************************************
   1132 **
   1133 ** Function         HAL_NfcPrmSetI2cPatch
   1134 **
   1135 ** Description      Specify patchfile for BCM20791B3 I2C fix. This fix
   1136 **                  must be downloaded prior to initial patch download for I2C
   1137 **                  transport
   1138 **
   1139 ** Input Params     p_i2c_patchfile_buf: pointer to patch for i2c fix
   1140 **                  i2c_patchfile_len: length of patch
   1141 **                  prei2c_delay: the delay before downloading main patch
   1142 **                                if 0 is given, NFC_HAL_PRM_POST_I2C_FIX_DELAY is used instead.
   1143 **
   1144 ** Returns          Nothing
   1145 **
   1146 **
   1147 *******************************************************************************/
   1148 void HAL_NfcPrmSetI2cPatch (UINT8 *p_i2c_patchfile_buf, UINT16 i2c_patchfile_len, UINT32 prei2c_delay)
   1149 {
   1150 #if (defined (NFC_HAL_PRE_I2C_PATCH_INCLUDED) && (NFC_HAL_PRE_I2C_PATCH_INCLUDED == TRUE))
   1151     HAL_TRACE_API0 ("HAL_NfcPrmSetI2cPatch ()");
   1152 
   1153     nfc_hal_cb.prm_i2c.prei2c_delay    = NFC_HAL_PRM_POST_I2C_FIX_DELAY;
   1154     if (prei2c_delay)
   1155         nfc_hal_cb.prm_i2c.prei2c_delay = prei2c_delay;
   1156     nfc_hal_cb.prm_i2c.p_patch = p_i2c_patchfile_buf;
   1157     nfc_hal_cb.prm_i2c.len = i2c_patchfile_len;
   1158 #endif  /* NFC_HAL_PRE_I2C_PATCH_INCLUDED */
   1159 }
   1160 
   1161 /*******************************************************************************
   1162 **
   1163 ** Function         HAL_NfcPrmSetSpdNciCmdPayloadSize
   1164 **
   1165 ** Description      Set Host-to-NFCC NCI message size for secure patch download
   1166 **
   1167 **                  This API must be called before calling HAL_NfcPrmDownloadStart.
   1168 **                  If the API is not called, then PRM will use the default
   1169 **                  message size.
   1170 **
   1171 **                  Typically, this API is only called for platforms that have
   1172 **                  message-size limitations in the transport/driver.
   1173 **
   1174 **                  Valid message size range: NFC_HAL_PRM_MIN_NCI_CMD_PAYLOAD_SIZE to 255.
   1175 **
   1176 ** Returns          HAL_NFC_STATUS_OK if successful
   1177 **                  HAL_NFC_STATUS_FAILED otherwise
   1178 **
   1179 **
   1180 *******************************************************************************/
   1181 tHAL_NFC_STATUS HAL_NfcPrmSetSpdNciCmdPayloadSize (UINT8 max_payload_size)
   1182 {
   1183     /* Validate: minimum size is NFC_HAL_PRM_MIN_NCI_CMD_PAYLOAD_SIZE */
   1184     if (max_payload_size < NFC_HAL_PRM_MIN_NCI_CMD_PAYLOAD_SIZE)
   1185     {
   1186         HAL_TRACE_ERROR2 ("HAL_NfcPrmSetSpdNciCmdPayloadSize: invalid size (%i). Must be between %i and 255", max_payload_size, NFC_HAL_PRM_MIN_NCI_CMD_PAYLOAD_SIZE);
   1187         return (HAL_NFC_STATUS_FAILED);
   1188     }
   1189     else
   1190     {
   1191         HAL_TRACE_API1 ("HAL_NfcPrmSetSpdNciCmdPayloadSize: new message size during download: %i", max_payload_size);
   1192         nfc_hal_cb.ncit_cb.nci_ctrl_size = max_payload_size;
   1193         return (HAL_NFC_STATUS_OK);
   1194     }
   1195 }
   1196