1 //*****************************************************************************
2 //
3 //! @file am_hal_ble.c
4 //!
5 //! @brief HAL Functions for the BLE Interface.
6 //!
7 //! @addtogroup BLE3 BLE - BLE functions
8 //! @ingroup apollo3_hal
9 //! @{
10 //
11 //*****************************************************************************
12 
13 //*****************************************************************************
14 //
15 // Copyright (c) 2024, Ambiq Micro, Inc.
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are met:
20 //
21 // 1. Redistributions of source code must retain the above copyright notice,
22 // this list of conditions and the following disclaimer.
23 //
24 // 2. Redistributions in binary form must reproduce the above copyright
25 // notice, this list of conditions and the following disclaimer in the
26 // documentation and/or other materials provided with the distribution.
27 //
28 // 3. Neither the name of the copyright holder nor the names of its
29 // contributors may be used to endorse or promote products derived from this
30 // software without specific prior written permission.
31 //
32 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
33 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
36 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
37 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
40 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 // POSSIBILITY OF SUCH DAMAGE.
43 //
44 // This is part of revision release_sdk_3_2_0-dd5f40c14b of the AmbiqSuite Development Package.
45 //
46 //*****************************************************************************
47 
48 #include <stdint.h>
49 #include <stdbool.h>
50 #include <string.h>
51 #include "am_mcu_apollo.h"
52 #include "am_hal_ble_patch.h"
53 #include "am_hal_ble_patch_b0.h"
54 
55 //*****************************************************************************
56 //
57 // Globals
58 //
59 //*****************************************************************************
60 am_hal_ble_state_t g_sBLEState[AM_REG_BLEIF_NUM_MODULES];
61 
62 //*****************************************************************************
63 //
64 //! Helper macros for rev B0 parts.
65 //
66 //*****************************************************************************
67 #define BLEIF_INTSTAT_BLECSSTATN_Msk    BLEIF_INTSTAT_B2MSHUTDN_Msk
68 #define BLEIF_INTSTAT_BLECIRQN_Msk      BLEIF_INTSTAT_B2MACTIVE_Msk
69 
70 #define SKIP_FALLING_EDGES 0
71 
72 //*****************************************************************************
73 //
74 //! SPI "options"
75 //!
76 //! These values affect the behavior of the BLE HAL in regards to the SPI bus,
77 //! but end users aren't likely to need to modify them. They are collected here
78 //! for testing and debugging purposes.
79 //
80 //*****************************************************************************
81 //! The amount of extra delay to add between successive SPI TX packets (in
82 //! microseconds).
83 #define AM_BLE_TX_PACKET_SPACING_US     1
84 
85 //! The BLE core takes a little while to wake up from a fresh boot, which means
86 //! that the patch_apply function might time-out on the first few tries. Set
87 //! this variable to let it try again for a finite number of trials.
88 #define AM_BLE_NUM_PATCH_TRIALS         5000
89 
90 //! Patch complete can also take some time.
91 #define AM_BLE_NUM_PATCH_CMP_TRIALS     5000
92 
93 //! How long the MCU should wait for SPI_STATUS before assuming the BLE core is
94 //! busy (measured in 10 us increments).
95 #define AM_BLE_STATUS_TIMEOUT           300
96 
97 //*****************************************************************************
98 //
99 //! Private types.
100 //
101 //*****************************************************************************
102 #define AM_HAL_MAGIC_BLE        0x775230
103 
104 #define AM_HAL_BLE_CHK_HANDLE(h)                                              \
105     ((h) && ((am_hal_handle_prefix_t *)(h))->s.bInit                          \
106      && (((am_hal_handle_prefix_t *)(h))->s.magic == AM_HAL_MAGIC_BLE))
107 
108 //*****************************************************************************
109 //
110 //! BLE Core maximum patch packet size.
111 //
112 //! Specified as part of the protocol.
113 //
114 //*****************************************************************************
115 #define MAX_PATCH_PACKET_LEN    0x80
116 
117 //*****************************************************************************
118 //
119 //! Some of the NationZ register addresses are different between A1/A2 and B0.
120 //
121 //*****************************************************************************
122 
123 #define AM_HAL_BLE_IP_RAM_32K_CLOCK_ADDR_A1         0x20006054
124 #define AM_HAL_BLE_IP_RAM_MODEX_TRIM_ADDR_A1        0x20006070
125 #define AM_HAL_BLE_IP_RAM_POWER_LEVEL_ADDR_A1       0x20006038
126 #define AM_HAL_BLE_IP_RAM_SLEEP_ENABLE_ADDR_A1      (0x200067b8 + 0x0c)
127 
128 #define AM_HAL_BLE_IP_RAM_32K_CLOCK_ADDR_B0         0x20006858
129 #define AM_HAL_BLE_IP_RAM_MODEX_TRIM_ADDR_B0        0x20006874
130 #define AM_HAL_BLE_IP_RAM_POWER_LEVEL_ADDR_B0       0x20006838
131 #define AM_HAL_BLE_IP_RAM_SLEEP_ENABLE_ADDR_B0      (0x20006e0c + 0x0c)
132 
133 //*****************************************************************************
134 //
135 //! Static function prototypes.
136 //
137 //*****************************************************************************
138 static bool am_hal_ble_bus_lock(am_hal_ble_state_t *pBle);
139 static void am_hal_ble_bus_release(am_hal_ble_state_t *pBle);
140 static uint32_t am_hal_ble_fifo_drain(void *pHandle);
141 static void am_hal_ble_fifo_read(void *pHandle, uint32_t *pui32Data, uint32_t ui32NumBytes);
142 static bool am_hal_ble_check_status(am_hal_ble_state_t *pBle);
143 static bool am_hal_ble_check_irq(am_hal_ble_state_t *pBle);
144 static uint32_t am_hal_ble_cmd_write(void *pHandle, am_hal_ble_transfer_t *psTransfer);
145 static uint32_t am_hal_ble_load_modex_trim_set(void *pHandle);
146 static uint32_t nonblocking_write(am_hal_ble_state_t *pBle, am_hal_ble_transfer_t *psTransfer);
147 static uint32_t nonblocking_read(am_hal_ble_state_t *pBle, am_hal_ble_transfer_t *psTransfer);
148 static uint8_t am_hal_ble_read_trimdata_from_info1(void);
149 static uint32_t am_util_ble_platform_reset(void *pHandle);
150 
151 //*****************************************************************************
152 //
153 //! Look up Table for NZ CRC16 generation
154 //
155 //*****************************************************************************
156 static const uint16_t ccitt_table[] =
157 {
158     0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011,
159     0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022,
160     0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072,
161     0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041,
162     0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2,
163     0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1,
164     0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1,
165     0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082,
166     0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192,
167     0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1,
168     0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1,
169     0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2,
170     0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151,
171     0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162,
172     0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132,
173     0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101,
174     0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312,
175     0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321,
176     0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371,
177     0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342,
178     0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1,
179     0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2,
180     0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2,
181     0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381,
182     0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291,
183     0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2,
184     0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2,
185     0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1,
186     0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252,
187     0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261,
188     0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231,
189     0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202
190 };
191 
192 //*****************************************************************************
193 //
194 //! Helper macros for delays.
195 //
196 //*****************************************************************************
197 #define delay_ms(ms)        am_hal_flash_delay(FLASH_CYCLES_US(1000 * (ms)))
198 #define delay_us(us)        am_hal_flash_delay(FLASH_CYCLES_US(us))
199 
200 #define WHILE_TIMEOUT_MS(expr, timeout, error)                                \
201     {                                                                         \
202         uint32_t ui32Timeout = 0;                                             \
203         while (expr)                                                          \
204         {                                                                     \
205             if (ui32Timeout >= (timeout * 1000))                              \
206             {                                                                 \
207                 return error;                                                 \
208             }                                                                 \
209                                                                               \
210             delay_us(1);                                                      \
211             ui32Timeout++;                                                    \
212         }                                                                     \
213     }
214 
215 #define WHILE_TIMEOUT_MS_BREAK(expr, timeout, error)                                \
216     {                                                                         \
217         uint32_t ui32Timeout = 0;                                             \
218         while (expr)                                                          \
219         {                                                                     \
220             if (ui32Timeout >= (timeout * 1000))                              \
221             {                                                                 \
222                 break;                                                 \
223             }                                                                 \
224                                                                               \
225             delay_us(1);                                                      \
226             ui32Timeout++;                                                    \
227         }                                                                     \
228     }
229 
230 //*****************************************************************************
231 //
232 //!  @brief  Helper function for checking BLE data.
233 //!
234 //!  @param b1
235 //!  @param b2
236 //!  @param len
237 //!  @return true
238 //!  @return false
239 //
240 //*****************************************************************************
241 static bool
buffer_compare(void * b1,void * b2,uint32_t len)242 buffer_compare(void *b1, void *b2, uint32_t len)
243 {
244     uint8_t *p1 = b1;
245     uint8_t *p2 = b2;
246 
247     for (uint32_t i = 0; i < len; i++)
248     {
249         if (p1[i] != p2[i])
250         {
251             return false;
252         }
253     }
254 
255     return true;
256 }
257 
258 //*****************************************************************************
259 //
260 //!  @brief Helper function for CRC caculation of BLE patch.
261 //!
262 //!  @param pui8Data
263 //!  @param len
264 //!  @return uint16_t
265 //
266 //*****************************************************************************
267 static uint16_t
am_hal_ble_crc_nz(uint8_t * pui8Data,uint32_t len)268 am_hal_ble_crc_nz(uint8_t *pui8Data, uint32_t len)
269 {
270     uint16_t ui16CurValue = 0;
271     uint32_t i;
272 
273     for (i = 0; i < len; i++)
274     {
275         ui16CurValue = ccitt_table[(((uint8_t)(ui16CurValue >> 8)) ^ pui8Data[i]) & 0xFF] ^ (ui16CurValue << 8);
276     }
277 
278     return ((ui16CurValue ^ 0) & ((1 << 16) - 1));
279 }
280 
281 //*****************************************************************************
282 //!
283 //!  @brief Default options for the BLE module.
284 //!
285 //*****************************************************************************
286 const am_hal_ble_config_t am_hal_ble_default_config =
287 {
288     //! Configure the HCI interface clock for 6 MHz
289     .ui32SpiClkCfg = AM_HAL_BLE_HCI_CLK_DIV8,
290 
291     //! Set HCI read and write thresholds to 32 bytes each.
292     .ui32ReadThreshold = 32,
293     .ui32WriteThreshold = 32,
294 
295     //! The MCU will supply the clock to the BLE core.
296     .ui32BleClockConfig = AM_HAL_BLE_CORE_MCU_CLK,
297 
298     //! Default settings for expected BLE clock drift.
299     .ui32ClockDrift = 0,
300     .ui32SleepClockDrift = 50,
301 
302     //! Default setting: AGC Enabled
303     .bAgcEnabled = true,
304 
305     //! Default setting:  Sleep Algo enabled
306     .bSleepEnabled = true,
307 
308     //! Apply the default patches when am_hal_ble_boot() is called.
309     .bUseDefaultPatches = true,
310 };
311 
312 //*****************************************************************************
313 //
314 // Function for controlling the WAKE signal.
315 //
316 //*****************************************************************************
317 uint32_t
am_hal_ble_wakeup_set(void * pHandle,uint32_t ui32Mode)318 am_hal_ble_wakeup_set(void *pHandle, uint32_t ui32Mode)
319 {
320     am_hal_ble_state_t *pBle = pHandle;
321 
322     //
323     // Check the handle.
324     //
325     if ( !AM_HAL_BLE_CHK_HANDLE(pHandle) )
326     {
327         return AM_HAL_STATUS_INVALID_HANDLE;
328     }
329 
330 //    am_hal_debug_gpio_set(BLE_DEBUG_TRACE_08);
331 
332     if ( ui32Mode )
333     {
334         BLEIFn(pBle->ui32Module)->BLECFG_b.WAKEUPCTL = BLEIF_BLECFG_WAKEUPCTL_ON;
335         am_hal_debug_gpio_set(BLE_DEBUG_TRACE_08);
336     }
337     else
338     {
339 #ifndef AM_DISABLE_BLE_SLEEP
340         BLEIFn(pBle->ui32Module)->BLECFG_b.WAKEUPCTL = BLEIF_BLECFG_WAKEUPCTL_OFF;
341         am_hal_debug_gpio_clear(BLE_DEBUG_TRACE_08);
342 #endif
343     }
344 
345     return AM_HAL_STATUS_SUCCESS;
346 
347 //    am_hal_debug_gpio_clear(BLE_DEBUG_TRACE_08);
348 }
349 
350 //*****************************************************************************
351 //
352 // Buffer for patch data.
353 //
354 //*****************************************************************************
355 am_hal_ble_buffer(128 + 4) g_psPatchBuffer;
356 
357 //*****************************************************************************
358 //
359 // Initialize the global variables associated with a BLE module, and return its
360 // handle.
361 //
362 //*****************************************************************************
363 uint32_t
am_hal_ble_initialize(uint32_t ui32Module,void ** ppHandle)364 am_hal_ble_initialize(uint32_t ui32Module, void **ppHandle)
365 {
366     //
367     // Check the arguments.
368     //
369     if (ui32Module >= AM_REG_BLEIF_NUM_MODULES)
370     {
371         return AM_HAL_STATUS_OUT_OF_RANGE;
372     }
373 
374     if (!ppHandle)
375     {
376         return AM_HAL_STATUS_INVALID_ARG;
377     }
378 
379     //
380     // Check if the handle is unallocated.
381     //
382     if (g_sBLEState[ui32Module].prefix.s.bInit)
383     {
384         return AM_HAL_STATUS_INVALID_OPERATION;
385     }
386 
387     //
388     // Initialize the handle.
389     //
390     memset(&g_sBLEState[ui32Module].sCurrentTransfer, 0, sizeof(am_hal_ble_transfer_t));
391     memset(&g_sBLEState[ui32Module].sSavedTransfer, 0, sizeof(am_hal_ble_transfer_t));
392 
393     g_sBLEState[ui32Module].prefix.s.bInit = true;
394     g_sBLEState[ui32Module].prefix.s.magic = AM_HAL_MAGIC_BLE;
395     g_sBLEState[ui32Module].ui32Module = ui32Module;
396     g_sBLEState[ui32Module].ui32TransferIndex = 0;
397     g_sBLEState[ui32Module].bPatchComplete = 0;
398     g_sBLEState[ui32Module].bContinuePacket = 0;
399     g_sBLEState[ui32Module].bSavedPacket = 0;
400     g_sBLEState[ui32Module].bBusy = 0;
401     g_sBLEState[ui32Module].bCmdComplete = 0;
402     g_sBLEState[ui32Module].bDmaComplete = 0;
403     g_sBLEState[ui32Module].bFlowControlComplete = 0;
404     g_sBLEState[ui32Module].bUseDefaultPatches = false;
405 
406     //
407     // Pass the handle back to the caller.
408     //
409     *ppHandle = &g_sBLEState[ui32Module];
410 
411     //
412     // Return the status.
413     //
414     return AM_HAL_STATUS_SUCCESS;
415 } // am_hal_ble_initialize()
416 
417 //*****************************************************************************
418 //
419 // Initialize the global variables associated with a BLE module, and return its
420 // handle.
421 //
422 //*****************************************************************************
423 uint32_t
am_hal_ble_deinitialize(void * pHandle)424 am_hal_ble_deinitialize(void *pHandle)
425 {
426     am_hal_ble_state_t *pBLE = (am_hal_ble_state_t *)pHandle;
427 
428     //
429     // Check the handle.
430     //
431     if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
432     {
433         return AM_HAL_STATUS_INVALID_HANDLE;
434     }
435 
436     //
437     // Initialize the handle.
438     //
439     memset(&(pBLE->sCurrentTransfer), 0, sizeof(am_hal_ble_transfer_t));
440 
441     pBLE->prefix.s.bInit = false;
442     pBLE->prefix.s.magic = 0;
443     pBLE->ui32Module = 0;
444     pBLE->ui32TransferIndex = 0;
445     pBLE->bPatchComplete = 0;
446     pBLE->bContinuePacket = 0;
447     pBLE->bSavedPacket = 0;
448     pBLE->bBusy = 0;
449     pBLE->bCmdComplete = 0;
450     pBLE->bDmaComplete = 0;
451     pBLE->bFlowControlComplete = 0;
452 
453     //
454     // Return the status.
455     //
456     return AM_HAL_STATUS_SUCCESS;
457 } // am_hal_ble_deinitialize()
458 
459 //*****************************************************************************
460 //
461 // Configuration function.
462 //
463 //*****************************************************************************
464 uint32_t
am_hal_ble_config(void * pHandle,const am_hal_ble_config_t * psConfig)465 am_hal_ble_config(void *pHandle, const am_hal_ble_config_t *psConfig)
466 {
467     uint32_t ui32Module;
468     uint32_t ui32BleClkConfig;
469 
470     //
471     // Check the handle.
472     //
473     if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
474     {
475         return AM_HAL_STATUS_INVALID_HANDLE;
476     }
477 
478     //
479     // Handle is good, so get the module number.
480     //
481     ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
482 
483     //
484     // Configure the SPI.
485     //
486     BLEIFn(ui32Module)->MSPICFG = 0x3;
487     BLEIFn(ui32Module)->MSPICFG_b.RDFC = 0;
488     BLEIFn(ui32Module)->MSPICFG_b.WTFC = 0;
489     BLEIFn(ui32Module)->MSPICFG_b.WTFCPOL = 1;
490     BLEIFn(ui32Module)->FIFOTHR_b.FIFOWTHR = psConfig->ui32WriteThreshold;
491     BLEIFn(ui32Module)->FIFOTHR_b.FIFORTHR = psConfig->ui32ReadThreshold;
492     BLEIFn(ui32Module)->FIFOCTRL |= BLEIF_FIFOCTRL_POPWR_Msk;
493 
494     //
495     // Clock configuration register writes need to be combined to a single
496     // operation.
497     //
498     ui32BleClkConfig =  _VAL2FLD(BLEIF_CLKCFG_FSEL, psConfig->ui32SpiClkCfg);
499     ui32BleClkConfig |= _VAL2FLD(BLEIF_CLKCFG_IOCLKEN, 1);
500 
501     if (psConfig->ui32BleClockConfig == AM_HAL_BLE_CORE_MCU_CLK)
502     {
503         ui32BleClkConfig |= _VAL2FLD(BLEIF_CLKCFG_CLK32KEN, 1);
504     }
505 
506     BLEIFn(ui32Module)->CLKCFG = ui32BleClkConfig;
507 
508     if (APOLLO3_A1)
509     {
510         //
511         // Modify the BLE core's NVDS settings to match our configuration.
512         //
513         uint8_t *pui8NVDSData = (uint8_t *) am_ble_nvds_patch.pui32Data;
514 
515         //
516         // Set the clock source.
517         //
518         pui8NVDSData[AM_HAL_BLE_NVDS_CLOCKSOURCE_OFFSET + 3] =
519             (psConfig->ui32BleClockConfig & 0xFF);
520 
521         //
522         // Set the expected BLE clock drift PPM
523         //
524         pui8NVDSData[AM_HAL_BLE_NVDS_CLOCKDRIFT_OFFSET + 3] =
525             (psConfig->ui32ClockDrift & 0x00FF);
526 
527         pui8NVDSData[AM_HAL_BLE_NVDS_CLOCKDRIFT_OFFSET + 4] =
528             (psConfig->ui32ClockDrift & 0xFF00) >> 8;
529 
530         //
531         // Set the sleep clock drift PPM.
532         //
533         pui8NVDSData[AM_HAL_BLE_NVDS_SLEEPCLOCKDRIFT_OFFSET + 3] =
534             (psConfig->ui32SleepClockDrift & 0x00FF);
535 
536         pui8NVDSData[AM_HAL_BLE_NVDS_SLEEPCLOCKDRIFT_OFFSET + 4] =
537             (psConfig->ui32SleepClockDrift & 0xFF00) >> 8;
538 
539         //
540         // Configure Sleep mode.
541         //
542         pui8NVDSData[AM_HAL_BLE_NVDS_SLEEPENABLE_OFFSET + 3] = (psConfig->bSleepEnabled == true) ? 1 : 0;
543         //
544         // Configure AGC.
545         //
546         pui8NVDSData[AM_HAL_BLE_NVDS_AGC_OFFSET + 3] = (psConfig->bAgcEnabled == true) ? 1 : 0;
547 
548         //
549         // Update the CRC.
550         //
551         am_ble_nvds_patch.ui32CRC = am_hal_ble_crc_nz(pui8NVDSData,
552                                                       am_ble_nvds_patch.ui32Length);
553     }
554 
555     //
556     // Save the addresses to the patches we intend to use.
557     //
558     g_sBLEState[ui32Module].bUseDefaultPatches = psConfig->bUseDefaultPatches;
559 
560     //
561     // Return the status.
562     //
563     return AM_HAL_STATUS_SUCCESS;
564 } // am_hal_ble_config()
565 
566 //*****************************************************************************
567 //
568 // Enable BLE
569 //
570 //*****************************************************************************
571 uint32_t
am_hal_ble_power_control(void * pHandle,uint32_t ui32PowerState)572 am_hal_ble_power_control(void *pHandle, uint32_t ui32PowerState)
573 {
574     uint32_t ui32Module;
575 
576     //
577     // Check the handle.
578     //
579     if ( !AM_HAL_BLE_CHK_HANDLE(pHandle) )
580     {
581         return AM_HAL_STATUS_INVALID_HANDLE;
582     }
583 
584     //
585     // Handle is good, so get the module number.
586     //
587     ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
588 
589     if (ui32PowerState == AM_HAL_BLE_POWER_ACTIVE)
590     {
591         //
592         // Don't run this initialization if the BLE is already enabled.
593         //
594         if ( PWRCTRL->DEVPWRSTATUS_b.BLEL == 0)
595         {
596             MCUCTRL->FEATUREENABLE |= 1;
597             WHILE_TIMEOUT_MS ( ((MCUCTRL->FEATUREENABLE & 0x7) != 0x7), 100,
598                                AM_HAL_BLE_FEATURE_DISABLED );
599 
600             //
601             // Enable the BLE module.
602             //
603             if (am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_PERIPH_BLEL) !=
604                 AM_HAL_STATUS_SUCCESS)
605             {
606                 return AM_HAL_BLE_REGULATOR_FAILED;
607             }
608 
609             //
610             // Release the BLE module RESET, start the "power state machine", and
611             // enable the clocks.
612             //
613             BLEIFn(ui32Module)->CLKCFG = _VAL2FLD(BLEIF_CLKCFG_CLK32KEN, 1);
614             BLEIFn(ui32Module)->BLEDBG_b.DBGDATA = 1 << 14;
615 
616             //
617             // The reset bit is different between A0 and subsequent revisions.
618             //
619             if ( APOLLO3_GE_A1 )
620             {
621                 MCUCTRL->MISCCTRL_b.BLE_RESETN = 1;
622             }
623             else
624             {
625                 AM_REGVAL(0x40020198) = 0x1 << 2;
626             }
627 
628             delay_ms(5);
629             BLEIFn(ui32Module)->BLECFG_b.PWRSMEN = 1;
630 
631             //
632             // Wait for indication that the power is on.
633             //
634             WHILE_TIMEOUT_MS ( BLEIFn(ui32Module)->BSTATUS_b.PWRST != 3, 1000,
635                                AM_HAL_BLE_POWERUP_INCOMPLETE );
636         }
637     }
638     else if (ui32PowerState == AM_HAL_BLE_POWER_OFF)
639     {
640         //
641         // Reverse of power-up. Disable clocks, set reset, then disable power.
642         //
643         BLEIFn(ui32Module)->CLKCFG = 0;
644         BLEIF->BLEDBG_b.DBGDATA = 0;
645 
646         if ( APOLLO3_GE_A1 )
647         {
648             MCUCTRL->MISCCTRL_b.BLE_RESETN = 0;
649         }
650         else
651         {
652             AM_REGVAL(0x40020198) &= ~(0x1 << 2);
653         }
654 
655         BLEIF->BLECFG_b.PWRSMEN = 0;
656 
657         if (am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_BLEL) !=
658             AM_HAL_STATUS_SUCCESS)
659         {
660             return AM_HAL_BLE_SHUTDOWN_FAILED;
661         }
662 
663         delay_us(100);
664     }
665     else
666     {
667         return AM_HAL_STATUS_INVALID_OPERATION;
668     }
669 
670     //
671     // Return the status.
672     //
673     return AM_HAL_STATUS_SUCCESS;
674 } // am_hal_ble_power_control()
675 
676 //************************************************************************
677 //
678 // Platform Reset function
679 //
680 //************************************************************************
681 
682 static uint32_t
am_util_ble_platform_reset(void * pHandle)683 am_util_ble_platform_reset(void *pHandle)
684 {
685     am_hal_ble_buffer(16) sWriteCommand;
686     am_hal_ble_buffer(16) sResponse;
687     am_hal_ble_state_t *pBLE = pHandle;
688     uint32_t ui32IntEnable;
689 
690     uint32_t ui32Module = pBLE->ui32Module;
691 
692     // issue the HCI command with to reset hci
693     sWriteCommand.bytes[0] = 0x01;
694     sWriteCommand.bytes[1] = 0x11;
695     sWriteCommand.bytes[2] = 0xfc;
696     sWriteCommand.bytes[3] = 0x00;
697     //
698     // Temporarily disable BLE interrupts.
699     //
700     ui32IntEnable = BLEIFn(ui32Module)->INTEN;
701     BLEIFn(ui32Module)->INTEN = 0;
702 
703     am_hal_ble_blocking_hci_write(pBLE,
704                                   AM_HAL_BLE_RAW,
705                                   sWriteCommand.words,
706                                   4);
707 
708     BLEIFn(ui32Module)->BLEDBG_b.IOCLKON = 1;
709 
710     //
711     // Wait for the response.
712     //
713     for (uint32_t i = 0; i < 1000; i++)
714     {
715         if ( BLEIFn(ui32Module)->BSTATUS_b.BLEIRQ != 0 )
716         {
717             break;
718         }
719         else if (i == (1000 - 1))
720         {
721             return AM_HAL_BLE_NO_HCI_RESPONSE;
722         }
723         else
724         {
725             delay_ms(1);
726         }
727     }
728 
729     am_hal_ble_blocking_hci_read(pBLE, sResponse.words, 0);
730 
731     //
732     // Re-enable BLE interrupts.
733     //
734     BLEIFn(ui32Module)->INTCLR = ui32IntEnable;
735     BLEIFn(ui32Module)->INTEN = ui32IntEnable;
736 
737     return AM_HAL_STATUS_SUCCESS;
738 }
739 
740 
741  am_hal_ble_buffer(0x0064)am_ble_hw_patch_data =
742 {
743     .bytes =
744     {
745         0x00, 0x22, 0x64, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3c, 0xdd, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
746         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
747         0x00, 0x00, 0x00, 0x00,
748 
749         0x10, 0xbd, 0x00, 0x00, 0xcc, 0x6d, 0x00, 0x20, 0x10, 0xb5, 0x04, 0x46, 0x01, 0x20, 0x80, 0xf3,
750         0x10, 0x88, 0x09, 0x48, 0x00, 0x78, 0x55, 0x28, 0x01, 0xd1, 0x01, 0xf0, 0x35, 0xfb, 0x07, 0x48,
751         0x40, 0x68, 0x04, 0x60, 0xE5, 0x20, 0x80, 0x47, 0xE5, 0x20, 0x80, 0x47, 0xE5, 0x20, 0x80, 0x47,
752         0xE5, 0x20, 0x80, 0x47, 0x10, 0xbd, 0x00, 0x00, 0x68, 0x68, 0x00, 0x20, 0x20, 0x68, 0x00, 0x20,
753     }
754 };
755 
756 am_hal_ble_patch_t am_ble_hw_patch =
757 {
758     .ui32Type = 0xCC,
759     .ui32Length = 0x0064,
760     .ui32CRC = 0xc504,
761     .pui32Data = am_ble_hw_patch_data.words,
762 };
763 
am_hal_ble_patch_preload(void * pHandle)764 uint32_t am_hal_ble_patch_preload(void *pHandle)
765 {
766     uint32_t *pRamCode = NULL;
767 
768     if (APOLLO3_B0 || APOLLO3_GE_B0)
769     {
770         pRamCode = (uint32_t *) (am_ble_performance_patch_b0.pui32Data);
771     }
772     //don't download the patch here
773     //caculate the trim value and store in patch array.
774     am_hal_ble_default_trim_set_ramcode(pHandle);
775 
776     am_hal_ble_patch_complete(pHandle);
777 
778     am_hal_ble_plf_reg_write(pHandle, 0x43000004, 0xFFFFFFFF);
779     if (pRamCode)
780     {
781         am_hal_ble_plf_reg_write(pHandle, 0x43C00008, pRamCode[2]);
782         am_hal_ble_plf_reg_write(pHandle, 0x43C00000, pRamCode[3]);
783     }
784 
785     //reset pmu registers
786     am_hal_ble_plf_reg_write(pHandle, 0x45800008, 0xa6a);
787     am_hal_ble_plf_reg_write(pHandle, 0x4580000c, 0x535);
788     am_hal_ble_plf_reg_write(pHandle, 0x45800010, 0xa6a);
789     am_hal_ble_plf_reg_write(pHandle, 0x45800014, 0x535);
790     am_hal_ble_plf_reg_write(pHandle, 0x45800018, 0x10A);
791     am_hal_ble_plf_reg_write(pHandle, 0x4580001c, 0x42);
792     am_hal_ble_plf_reg_write(pHandle, 0x45800020, 0x42);
793     am_hal_ble_plf_reg_write(pHandle, 0x45800024, 0x42);
794     am_hal_ble_plf_reg_write(pHandle, 0x45800028, 0x10A);
795     am_hal_ble_plf_reg_write(pHandle, 0x4580002c, 0x10A);
796     am_hal_ble_plf_reg_write(pHandle, 0x45800050, 0x60);
797     am_hal_ble_plf_reg_write(pHandle, 0x45800064, 0x4);
798     am_hal_ble_plf_reg_write(pHandle, 0x45800078, 0x60);
799     am_hal_ble_plf_reg_write(pHandle, 0x45800080, 0x60);
800     am_hal_ble_plf_reg_write(pHandle, 0x45800094, 0x021E);
801     am_hal_ble_plf_reg_write(pHandle, 0x458000a0, 0x20);
802 
803     //download a hardware patch for performing a softreset
804     for (uint32_t i = 0; i < 25; i++)
805     {
806         am_hal_ble_plf_reg_write(pHandle, 0x20003E9C + i * 4, am_ble_hw_patch.pui32Data[i]);
807     }
808 
809     am_hal_ble_plf_reg_write(pHandle, 0x51C00018, am_ble_hw_patch.pui32Data[2]);
810     am_hal_ble_plf_reg_write(pHandle, 0x51C00014, am_ble_hw_patch.pui32Data[1]);
811     delay_ms(50);
812     am_util_ble_platform_reset(pHandle);
813     delay_ms(50);
814     am_hal_ble_state_t *pBLE1 = (am_hal_ble_state_t *)pHandle;
815     pBLE1->bPatchComplete = 0;
816     return AM_HAL_STATUS_SUCCESS;
817 }
818 
819 
820 //*****************************************************************************
821 //
822 // Perform all of the operations necessary to prepare  the BLE controller for
823 // HCI operation.
824 //
825 //*****************************************************************************
826 uint32_t
am_hal_ble_boot(void * pHandle)827 am_hal_ble_boot(void *pHandle)
828 {
829     uint32_t ui32Status;
830 
831     //
832     // Check the handle.
833     //
834     if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
835     {
836         return AM_HAL_STATUS_INVALID_HANDLE;
837     }
838 
839     //
840     // The handle is good, so we can access it as a structure.
841     //
842     am_hal_ble_state_t *pBLE = pHandle;
843 
844     if (pBLE->bUseDefaultPatches)
845     {
846         //
847         // The B0 silicon patching method is slightly different from A1. B0 silicon
848         // does not require the Copy Patch method introduced for A1 silicon.
849         //
850         if (APOLLO3_A0 || APOLLO3_A1)
851         {
852             ui32Status = am_hal_ble_default_copy_patch_apply(pHandle);
853             if (ui32Status != AM_HAL_STATUS_SUCCESS)
854             {
855                 return ui32Status;
856             }
857         }
858 
859         // B0 silicon patch load
860         if (APOLLO3_B0 || APOLLO3_GE_B0)
861         {
862             ui32Status = am_hal_ble_patch_preload(pHandle);
863             if (ui32Status != AM_HAL_STATUS_SUCCESS)
864             {
865                 return ui32Status;
866             }
867         }
868 
869         //
870         // Apply the BLE trim value
871         //
872         ui32Status = am_hal_ble_default_trim_set_ramcode(pHandle);
873         if (ui32Status != AM_HAL_STATUS_SUCCESS)
874         {
875             return ui32Status;
876         }
877 
878         //
879         // Apply the NVDS patch.
880         //
881         ui32Status = am_hal_ble_default_patch_apply(pHandle);
882         if (ui32Status != AM_HAL_STATUS_SUCCESS)
883         {
884             return ui32Status;
885         }
886 
887         //
888         // Complete the patching step
889         //
890         ui32Status = am_hal_ble_patch_complete(pHandle);
891         if (ui32Status != AM_HAL_STATUS_SUCCESS)
892         {
893             return ui32Status;
894         }
895     }
896 
897     if (am_hal_ble_check_32k_clock(pBLE) == AM_HAL_STATUS_FAIL)
898     {
899         return AM_HAL_BLE_32K_CLOCK_UNSTABLE;
900     }
901     else
902     {
903         return AM_HAL_STATUS_SUCCESS;
904     }
905 } // am_hal_ble_boot()
906 
907 //*****************************************************************************
908 //
909 // Apply a patch.
910 //
911 // Returns 0 for success or a numerical error code for failures.
912 //
913 //*****************************************************************************
914 uint32_t
am_hal_ble_patch_apply(void * pHandle,am_hal_ble_patch_t * psPatch)915 am_hal_ble_patch_apply(void *pHandle, am_hal_ble_patch_t *psPatch)
916 {
917     uint8_t pui8ExpectedResponse[32];
918     uint32_t ui32ErrorStatus;
919     uint32_t ui32Trial;
920 
921     //
922     // Check the handle.
923     //
924     if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
925     {
926         return AM_HAL_STATUS_INVALID_HANDLE;
927     }
928 
929     uint32_t ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
930     am_hal_ble_transfer_t sTransfer;
931     am_hal_ble_buffer(16) psPatchBuffer;
932 
933     //
934     // Send a header packet.
935     //
936     psPatchBuffer.bytes[0] = 0x01;
937     psPatchBuffer.bytes[1] = psPatch->ui32Type;
938     psPatchBuffer.bytes[2] = 0xF1;
939     psPatchBuffer.bytes[3] = 0x02;
940     psPatchBuffer.bytes[4] = (psPatch->ui32Length & 0xFF);
941     psPatchBuffer.bytes[5] = ((psPatch->ui32Length >> 8) & 0xFF);
942 
943     //
944     // This first packet might take a few tries.
945     //
946     for ( ui32Trial = 0; ui32Trial < AM_BLE_NUM_PATCH_TRIALS; ui32Trial++)
947     {
948         ui32ErrorStatus = am_hal_ble_blocking_hci_write(pHandle,
949                                                         AM_HAL_BLE_RAW,
950                                                         psPatchBuffer.words,
951                                                         6);
952 
953         if ( ui32ErrorStatus == AM_HAL_STATUS_SUCCESS )
954         {
955             break;
956         }
957     }
958 
959     if (ui32ErrorStatus != AM_HAL_STATUS_SUCCESS)
960     {
961         return ui32ErrorStatus;
962     }
963 
964     //
965     // Wait for the header response. It should be 5 bytes long.
966     //
967     WHILE_TIMEOUT_MS ( BLEIFn(ui32Module)->BSTATUS_b.BLEIRQ == 0, 1000,
968                        AM_HAL_BLE_NO_HCI_RESPONSE );
969 
970     memset(&sTransfer, 0, sizeof(am_hal_ble_transfer_t));
971     sTransfer.ui8Command = AM_HAL_BLE_READ;
972     sTransfer.pui32Data = psPatchBuffer.words;
973     sTransfer.ui16Length = 5;
974 
975     ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &sTransfer);
976     if ( ui32ErrorStatus != AM_HAL_STATUS_SUCCESS )
977     {
978         return ui32ErrorStatus;
979     }
980 
981     pui8ExpectedResponse[0] = 0x04;
982     pui8ExpectedResponse[1] = psPatch->ui32Type;
983     pui8ExpectedResponse[2] = 0xF1;
984     pui8ExpectedResponse[3] = 0x01;
985     pui8ExpectedResponse[4] = 0x00;
986 
987     if (!buffer_compare(psPatchBuffer.words, pui8ExpectedResponse, 5))
988     {
989         return AM_HAL_STATUS_FAIL;
990     }
991 
992     //
993     // Send all of the data, including the acknowledgements.
994     //
995     uint32_t ui32RemainingBytes = psPatch->ui32Length;
996     uint32_t ui32Index = 0;
997 
998     while (ui32RemainingBytes)
999     {
1000         //
1001         // Figure out how many bytes to send in the next packet.
1002         //
1003         uint32_t ui32TransferSize = (ui32RemainingBytes > MAX_PATCH_PACKET_LEN ?
1004                                      MAX_PATCH_PACKET_LEN : ui32RemainingBytes);
1005 
1006         //
1007         // Send a data header.
1008         //
1009         memset(&sTransfer, 0, sizeof(am_hal_ble_transfer_t));
1010         sTransfer.ui8Command = AM_HAL_BLE_WRITE;
1011         sTransfer.pui32Data = g_psPatchBuffer.words;
1012         sTransfer.ui16Length = ui32TransferSize + 4;
1013         sTransfer.bContinue = false;
1014 
1015         g_psPatchBuffer.bytes[0] = 0x01;
1016         g_psPatchBuffer.bytes[1] = psPatch->ui32Type;
1017         g_psPatchBuffer.bytes[2] = 0xF2;
1018         g_psPatchBuffer.bytes[3] = ui32TransferSize;
1019 
1020         // copy data into buffer
1021         memcpy(&g_psPatchBuffer.bytes[4], (uint8_t *)&(psPatch->pui32Data[ui32Index / 4]), ui32TransferSize);
1022 
1023         ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &sTransfer);
1024         if ( ui32ErrorStatus != AM_HAL_STATUS_SUCCESS )
1025         {
1026             return ui32ErrorStatus;
1027         }
1028 
1029         //
1030         // Read the acknowledgement.
1031         //
1032         WHILE_TIMEOUT_MS( BLEIFn(ui32Module)->BSTATUS_b.BLEIRQ == 0, 1000,
1033                           AM_HAL_BLE_NO_HCI_RESPONSE);
1034 
1035         memset(&sTransfer, 0, sizeof(am_hal_ble_transfer_t));
1036         sTransfer.ui8Command = AM_HAL_BLE_READ;
1037         sTransfer.pui32Data = psPatchBuffer.words;
1038         sTransfer.ui16Length = 5;
1039 
1040         ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &sTransfer);
1041         if ( ui32ErrorStatus != AM_HAL_STATUS_SUCCESS )
1042         {
1043             return ui32ErrorStatus;
1044         }
1045 
1046         pui8ExpectedResponse[0] = 0x04;
1047         pui8ExpectedResponse[1] = psPatch->ui32Type;
1048         pui8ExpectedResponse[2] = 0xF2;
1049         pui8ExpectedResponse[3] = 0x01;
1050         pui8ExpectedResponse[4] = 0x00;
1051 
1052         if (!buffer_compare(psPatchBuffer.words, pui8ExpectedResponse, 5))
1053         {
1054             return AM_HAL_STATUS_FAIL;
1055         }
1056 
1057         //
1058         // Update the tracking variables
1059         //
1060         ui32RemainingBytes -= ui32TransferSize;
1061         ui32Index += ui32TransferSize;
1062     }
1063 
1064     //
1065     // Send the CRC, and make sure we got it right.
1066     //
1067     psPatchBuffer.bytes[0] = 0x01;
1068     psPatchBuffer.bytes[1] = psPatch->ui32Type;
1069     psPatchBuffer.bytes[2] = 0xF3;
1070     psPatchBuffer.bytes[3] = 0x02;
1071     psPatchBuffer.bytes[4] = (psPatch->ui32CRC & 0xFF);
1072     psPatchBuffer.bytes[5] = ((psPatch->ui32CRC >> 8) & 0xFF);
1073 
1074     if (am_hal_ble_blocking_hci_write(pHandle, AM_HAL_BLE_RAW, psPatchBuffer.words, 6) !=
1075         AM_HAL_STATUS_SUCCESS)
1076     {
1077         return AM_HAL_STATUS_FAIL;
1078     }
1079 
1080     //
1081     // Wait for the header response. It should be 5 bytes long.
1082     //
1083     WHILE_TIMEOUT_MS( BLEIFn(ui32Module)->BSTATUS_b.BLEIRQ == 0, 1000,
1084                       AM_HAL_BLE_NO_HCI_RESPONSE );
1085 
1086     memset(&sTransfer, 0, sizeof(am_hal_ble_transfer_t));
1087     sTransfer.ui8Command = AM_HAL_BLE_READ;
1088     sTransfer.pui32Data = psPatchBuffer.words;
1089     sTransfer.ui16Length = 5;
1090 
1091     ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &sTransfer);
1092     if ( ui32ErrorStatus != AM_HAL_STATUS_SUCCESS )
1093     {
1094         return ui32ErrorStatus;
1095     }
1096 
1097     pui8ExpectedResponse[0] = 0x04;
1098     pui8ExpectedResponse[1] = psPatch->ui32Type;
1099     pui8ExpectedResponse[2] = 0xF3;
1100     pui8ExpectedResponse[3] = 0x01;
1101     pui8ExpectedResponse[4] = 0x00;
1102 
1103     if (!buffer_compare(psPatchBuffer.words, pui8ExpectedResponse, 5))
1104     {
1105         return AM_HAL_STATUS_FAIL;
1106     }
1107     else
1108     {
1109         return AM_HAL_STATUS_SUCCESS;
1110     }
1111 } // am_hal_ble_patch_apply()
1112 
1113 //*****************************************************************************
1114 // @brief
1115 //
1116 // @param pHandle
1117 // @return uint32_t
1118 //*****************************************************************************
1119 
1120 uint32_t
am_hal_ble_patch_copy_end_apply(void * pHandle)1121 am_hal_ble_patch_copy_end_apply(void *pHandle)
1122 {
1123     uint8_t pui8ExpectedResponse[32];
1124     uint32_t ui32ErrorStatus;
1125     uint32_t ui32Trial;
1126 
1127     //
1128     // Check the handle.
1129     //
1130     if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
1131     {
1132         return AM_HAL_STATUS_INVALID_HANDLE;
1133     }
1134 
1135     uint32_t ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
1136     am_hal_ble_transfer_t sTransfer;
1137     am_hal_ble_buffer(16) psPatchBuffer;
1138 
1139     //
1140     // Send a header packet.
1141     //
1142     psPatchBuffer.bytes[0] = 0x01;
1143     psPatchBuffer.bytes[1] = 0xEE;
1144     psPatchBuffer.bytes[2] = 0xF1;
1145     psPatchBuffer.bytes[3] = 0x02;
1146     psPatchBuffer.bytes[4] = 0x00;
1147     psPatchBuffer.bytes[5] = 0x00;
1148 
1149     //
1150     // This first packet might take a few tries.
1151     //
1152     for ( ui32Trial = 0; ui32Trial < AM_BLE_NUM_PATCH_TRIALS; ui32Trial++)
1153     {
1154         ui32ErrorStatus = am_hal_ble_blocking_hci_write(pHandle,
1155                                                         AM_HAL_BLE_RAW,
1156                                                         psPatchBuffer.words,
1157                                                         6);
1158 
1159         if ( ui32ErrorStatus == AM_HAL_STATUS_SUCCESS )
1160         {
1161 
1162             break;
1163         }
1164     }
1165 
1166     if (ui32ErrorStatus != AM_HAL_STATUS_SUCCESS)
1167     {
1168 
1169         return ui32ErrorStatus;
1170     }
1171 
1172     //
1173     // Wait for the header response. It should be 5 bytes long.
1174     //
1175     WHILE_TIMEOUT_MS( BLEIFn(ui32Module)->BSTATUS_b.BLEIRQ == 0, 1000, AM_HAL_BLE_NO_HCI_RESPONSE);
1176 
1177     memset(&sTransfer, 0, sizeof(am_hal_ble_transfer_t));
1178     sTransfer.ui8Command = AM_HAL_BLE_READ;
1179     sTransfer.pui32Data = psPatchBuffer.words;
1180     sTransfer.ui16Length = 5;
1181 
1182     ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &sTransfer);
1183     if ( ui32ErrorStatus != AM_HAL_STATUS_SUCCESS )
1184     {
1185 
1186         return ui32ErrorStatus;
1187     }
1188 
1189     pui8ExpectedResponse[0] = 0x04;
1190     pui8ExpectedResponse[1] = 0xEE;
1191     pui8ExpectedResponse[2] = 0xF1;
1192     pui8ExpectedResponse[3] = 0x01;
1193     pui8ExpectedResponse[4] = 0x00;
1194 
1195     if (!buffer_compare(psPatchBuffer.words, pui8ExpectedResponse, 5))
1196     {
1197 
1198         return AM_HAL_STATUS_FAIL;
1199     }
1200     return 0;
1201 } // am_hal_ble_patch_copy_end_apply()
1202 
1203 //*****************************************************************************
1204 //
1205 // Apply the default copy patch.
1206 //
1207 // Returns 0 for success or a numerical error code for failures.
1208 //
1209 //*****************************************************************************
1210 uint32_t
am_hal_ble_default_copy_patch_apply(void * pHandle)1211 am_hal_ble_default_copy_patch_apply(void *pHandle)
1212 {
1213     uint32_t ui32Status;
1214     uint16_t ui16Crc;
1215 
1216     am_hal_ble_patch_t **psCopyPatch;
1217 
1218     psCopyPatch = am_hal_ble_default_copy_patches;
1219 
1220     ui16Crc = am_hal_ble_crc_nz((uint8_t*)(psCopyPatch[0]->pui32Data), psCopyPatch[0]->ui32Length);
1221     psCopyPatch[0]->ui32CRC = ui16Crc;
1222     ui32Status = am_hal_ble_patch_apply(pHandle, psCopyPatch[0]);
1223     if (ui32Status != AM_HAL_STATUS_SUCCESS)
1224     {
1225         return ui32Status;
1226     }
1227 
1228     ui32Status = am_hal_ble_patch_copy_end_apply(pHandle);
1229     if ( ui32Status != AM_HAL_STATUS_SUCCESS )
1230     {
1231         return ui32Status;
1232     }
1233 
1234     return AM_HAL_STATUS_SUCCESS;
1235 }
1236 
1237 //*****************************************************************************
1238 //
1239 // Apply the default patch.
1240 //
1241 // Returns 0 for success or a numerical error code for failures.
1242 //
1243 //*****************************************************************************
1244 uint32_t
am_hal_ble_default_patch_apply(void * pHandle)1245 am_hal_ble_default_patch_apply(void *pHandle)
1246 {
1247     uint32_t ui32Status, i = 0;
1248     uint16_t ui16Crc;
1249     uint32_t ui32NumPatches;
1250     am_hal_ble_patch_t **psDefaultPatches;
1251 
1252     if (APOLLO3_A0 || APOLLO3_A1)
1253     {
1254         ui32NumPatches = am_hal_ble_num_default_patches;
1255         psDefaultPatches = am_hal_ble_default_patches;
1256     }
1257     else if (APOLLO3_B0)
1258     {
1259         ui32NumPatches = am_hal_ble_num_default_patches_b0;
1260         psDefaultPatches = am_hal_ble_default_patches_b0;
1261     }
1262     else
1263     {
1264         return AM_HAL_STATUS_FAIL;
1265     }
1266 
1267     for ( i = 0; i < ui32NumPatches; i++ )
1268     {
1269         ui16Crc = am_hal_ble_crc_nz((uint8_t*)(psDefaultPatches[i]->pui32Data), psDefaultPatches[i]->ui32Length);
1270         psDefaultPatches[i]->ui32CRC = ui16Crc;
1271         ui32Status = am_hal_ble_patch_apply(pHandle, psDefaultPatches[i]);
1272         if (ui32Status != AM_HAL_STATUS_SUCCESS)
1273         {
1274             return ui32Status;
1275         }
1276     }
1277 
1278     return AM_HAL_STATUS_SUCCESS;
1279 } // am_hal_ble_default_patch_apply()
1280 
1281 //*****************************************************************************
1282 //
1283 // Complete the patching process
1284 //
1285 //*****************************************************************************
1286 uint32_t
am_hal_ble_patch_complete(void * pHandle)1287 am_hal_ble_patch_complete(void *pHandle)
1288 {
1289     uint32_t ui32ErrorStatus;
1290     am_hal_ble_transfer_t sTransfer;
1291     am_hal_ble_buffer(12) sTxBuffer;
1292     am_hal_ble_buffer(12) sRxBuffer;
1293     uint32_t ui32Trial;
1294 
1295     am_hal_ble_state_t *pBLE = pHandle;
1296 
1297     //
1298     // Check the handle.
1299     //
1300     if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
1301     {
1302         return AM_HAL_STATUS_INVALID_HANDLE;
1303     }
1304 
1305     uint32_t ui32Module = pBLE->ui32Module;
1306 
1307     //
1308     // Write the "patch complete" command.
1309     //
1310     memset(&sTransfer, 0, sizeof(am_hal_ble_transfer_t));
1311     sTransfer.ui8Command = AM_HAL_BLE_WRITE;
1312     sTransfer.pui32Data = sTxBuffer.words;
1313     sTransfer.ui16Length = 6;
1314 
1315     sTxBuffer.bytes[0] = 0x01;
1316     sTxBuffer.bytes[1] = 0xEE;
1317     sTxBuffer.bytes[2] = 0xF1;
1318     sTxBuffer.bytes[3] = 0x02;
1319     sTxBuffer.bytes[4] = 0x00;
1320     sTxBuffer.bytes[5] = 0x00;
1321 
1322     for ( ui32Trial = 0; ui32Trial < AM_BLE_NUM_PATCH_CMP_TRIALS; ui32Trial++)
1323     {
1324         ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &sTransfer);
1325         if ( ui32ErrorStatus == AM_HAL_STATUS_SUCCESS )
1326         {
1327             break;
1328         }
1329     }
1330 
1331     WHILE_TIMEOUT_MS ( BLEIFn(ui32Module)->BSTATUS_b.BLEIRQ == 0, 100,
1332                        AM_HAL_BLE_NO_HCI_RESPONSE );
1333 
1334     //
1335     // Read back the response.
1336     //
1337     sTransfer.ui8Command = AM_HAL_BLE_READ;
1338     sTransfer.pui32Data = sRxBuffer.words;
1339     sTransfer.ui16Length = 2;
1340     ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &sTransfer);
1341     if ( ui32ErrorStatus != AM_HAL_STATUS_SUCCESS )
1342     {
1343         return ui32ErrorStatus;
1344     }
1345 
1346     //
1347     // Check to see which format the response came back in. If it doesn't have
1348     // a 2-byte length header, we need to manually override the length, and
1349     // continue on to adjust the HCI format in the next packet. Otherwise, we
1350     // can just return from here.
1351     //
1352     if ( sRxBuffer.bytes[1] == 0xEE )
1353     {
1354         sTransfer.ui16Length = 3;
1355         ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &sTransfer);
1356         if ( ui32ErrorStatus != AM_HAL_STATUS_SUCCESS )
1357         {
1358             return ui32ErrorStatus;
1359         }
1360     }
1361     else
1362     {
1363         sTransfer.ui16Length = (sRxBuffer.bytes[0] + (sRxBuffer.bytes[1] << 8));
1364         ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &sTransfer);
1365         if ( ui32ErrorStatus != AM_HAL_STATUS_SUCCESS )
1366         {
1367             return ui32ErrorStatus;
1368         }
1369 
1370         //
1371         // Make sure to remember that we've sent the "patch complete" packet.
1372         //
1373         pBLE->bPatchComplete = true;
1374 
1375         return AM_HAL_STATUS_SUCCESS;
1376     }
1377 
1378     //
1379     // If we made it here, we need to tell the radio that we need two-byte
1380     // headers prepended to each HCI packet it sends us.
1381     //
1382     memset(&sTransfer, 0, sizeof(am_hal_ble_transfer_t));
1383     sTransfer.ui8Command = AM_HAL_BLE_WRITE;
1384     sTransfer.pui32Data = sTxBuffer.words;
1385     sTransfer.ui16Length = 5;
1386 
1387     sTxBuffer.bytes[0] = 0x01;
1388     sTxBuffer.bytes[1] = 0x04;
1389     sTxBuffer.bytes[2] = 0xFD;
1390     sTxBuffer.bytes[3] = 0x01;
1391     sTxBuffer.bytes[4] = 0x01;
1392 
1393     for ( ui32Trial = 0; ui32Trial < AM_BLE_NUM_PATCH_CMP_TRIALS; ui32Trial++)
1394     {
1395         ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &sTransfer);
1396         if ( ui32ErrorStatus == AM_HAL_STATUS_SUCCESS )
1397         {
1398             break;
1399         }
1400     }
1401 
1402     if (ui32ErrorStatus != AM_HAL_STATUS_SUCCESS)
1403     {
1404         return ui32ErrorStatus;
1405     }
1406 
1407     WHILE_TIMEOUT_MS ( BLEIFn(ui32Module)->BSTATUS_b.BLEIRQ == 0, 100,
1408                        AM_HAL_BLE_NO_HCI_RESPONSE );
1409 
1410     sTransfer.ui8Command = AM_HAL_BLE_READ;
1411     sTransfer.pui32Data = sRxBuffer.words;
1412     sTransfer.ui16Length = 9;
1413     ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &sTransfer);
1414     if ( ui32ErrorStatus != AM_HAL_STATUS_SUCCESS )
1415     {
1416         return ui32ErrorStatus;
1417     }
1418 
1419     //
1420     // Now that we're done patching, we can let the radio sleep.
1421     //
1422     am_hal_ble_wakeup_set(pBLE, 0);
1423 
1424     //
1425     // Make sure to remember that we've sent the "patch complete" packet.
1426     //
1427     pBLE->bPatchComplete = true;
1428 
1429     //
1430     // Delay to give the BLE core time to take the patch (assuming a patch was sent).
1431     //
1432     delay_ms(500);
1433 
1434     //
1435     // Load the modex trim data to the BLE controller.
1436     //
1437     am_hal_ble_load_modex_trim_set(pBLE);
1438 
1439     //
1440     // Return the status.
1441     //
1442     return AM_HAL_STATUS_SUCCESS;
1443 } // am_hal_ble_patch_complete()
1444 
1445 //*****************************************************************************
1446 //
1447 // Set one of the trim values for the BLE core.
1448 //
1449 //*****************************************************************************
1450 uint32_t
am_hal_ble_trim_set(void * pHandle,uint32_t ui32BleCoreAddress,uint32_t ui32TrimValue,uint32_t ui32TrimMask)1451 am_hal_ble_trim_set(void *pHandle, uint32_t ui32BleCoreAddress, uint32_t ui32TrimValue, uint32_t ui32TrimMask)
1452 {
1453     am_hal_ble_state_t *pBLE = pHandle;
1454     uint32_t ui32TrimValueSwapped, ui32LockValue, ui32ReadVal, ui32WriteVal;
1455 
1456     ui32TrimValueSwapped = (((ui32TrimValue & 0x000000FF) << 24) |
1457                             ((ui32TrimValue & 0x0000FF00) << 8) |
1458                             ((ui32TrimValue & 0x00FF0000) >> 8) |
1459                             ((ui32TrimValue & 0xFF000000) >> 24));
1460 
1461     if (ui32TrimValue != 0xFFFFFFFF)
1462     {
1463         //
1464         // Unlock the BLE registers and save the "lock register" value.
1465         //
1466         am_hal_ble_plf_reg_read(pBLE, 0x43000004, &ui32LockValue);
1467         am_hal_ble_plf_reg_write(pBLE, 0x43000004, 0xFFFFFFFF);
1468 
1469         //
1470         // Check to see if we need a bitfield mask. If not, we can just write
1471         // directly.
1472         //
1473         if (ui32TrimMask == 0xFFFFFFFF)
1474         {
1475             am_hal_ble_plf_reg_write(pBLE, ui32BleCoreAddress, ui32TrimValueSwapped);
1476         }
1477         else
1478         {
1479             //
1480             // If we do need a mask, read the register, mask out the old bits,
1481             // OR in the new, and write the new value back.
1482             //
1483             am_hal_ble_plf_reg_read(pBLE, ui32BleCoreAddress, &ui32ReadVal);
1484             ui32WriteVal = ((ui32ReadVal & (~ui32TrimMask)) | ui32TrimValueSwapped);
1485 
1486             am_hal_ble_plf_reg_write(pBLE, ui32BleCoreAddress, ui32WriteVal);
1487         }
1488 
1489         //
1490         // Unlock the BLE register.
1491         //
1492         am_hal_ble_plf_reg_write(pBLE, 0x43000004, ui32LockValue);
1493     }
1494 
1495     return AM_HAL_STATUS_SUCCESS;
1496 } // am_hal_ble_trim_set()
1497 
1498 //*****************************************************************************
1499 //
1500 // Set the bandgap voltage, bandgap current, and retention LDO output values
1501 // based on the tested values stored in non-volatile memory.
1502 //
1503 //*****************************************************************************
1504 uint32_t
am_hal_ble_default_trim_set_ramcode(void * pHandle)1505 am_hal_ble_default_trim_set_ramcode(void *pHandle)
1506 {
1507     uint32_t ui32TrimValue;
1508     uint32_t ui32TrimValueSwapped;
1509     uint32_t *pRamCode;
1510 
1511     if (APOLLO3_B0)
1512     {
1513         pRamCode = (uint32_t *) (am_ble_performance_patch_b0.pui32Data);
1514     }
1515     else
1516     {
1517         pRamCode = (uint32_t *) (am_ble_performance_patch.pui32Data);
1518     }
1519 
1520     //
1521     // Set the bandgap voltage and current.
1522     //
1523     //ui32TrimValue = (AM_REGVAL(0x50023800) | (0x0F000000)) & (0xEFFFFFFF);
1524     ui32TrimValue = AM_REGVAL(0x50023800);
1525     ui32TrimValueSwapped = (((ui32TrimValue & 0x000000FF) << 24) |
1526                             ((ui32TrimValue & 0x0000FF00) << 8) |
1527                             ((ui32TrimValue & 0x00FF0000) >> 8) |
1528                             ((ui32TrimValue & 0xFF000000) >> 24));
1529 
1530     if (ui32TrimValueSwapped != 0xFFFFFFFF)
1531     {
1532         pRamCode[2] = ui32TrimValueSwapped;
1533     }
1534 
1535     //
1536     // Set the retention LDO voltage.
1537     //
1538     ui32TrimValue = AM_REGVAL(0x50023804);
1539     if (ui32TrimValue != 0xFFFFFFFF)
1540     {
1541         // 0xFFFFFFFF means the part has not been trimed.
1542         ui32TrimValue += 0x40000000;  // Increase the retention voltage to > 0.75v
1543     }
1544     ui32TrimValueSwapped = (((ui32TrimValue & 0x000000FF) << 24) |
1545                             ((ui32TrimValue & 0x0000FF00) << 8) |
1546                             ((ui32TrimValue & 0x00FF0000) >> 8) |
1547                             ((ui32TrimValue & 0xFF000000) >> 24));
1548 
1549     if ( ui32TrimValueSwapped != 0xFFFFFFFF )
1550     {
1551         pRamCode[3] = ((pRamCode[3] & (~0x1F0)) | ui32TrimValueSwapped);
1552     }
1553 
1554     return AM_HAL_STATUS_SUCCESS;
1555 } // am_hal_ble_default_trim_set_ramcode()
1556 
1557 //*****************************************************************************
1558 //
1559 // Builds a vendor-specific BLE command.
1560 //
1561 //*****************************************************************************
1562 uint32_t
am_hal_ble_vs_command_build(uint32_t * pui32Command,uint32_t ui32OpCode,uint32_t ui32TotalLength,uint8_t * pui8Parameters)1563 am_hal_ble_vs_command_build(uint32_t *pui32Command, uint32_t ui32OpCode,
1564                             uint32_t ui32TotalLength, uint8_t *pui8Parameters)
1565 {
1566     uint8_t *pui8Dest = (uint8_t *) pui32Command;
1567 
1568     //
1569     // Build the header portion of the command from the given argments.
1570     //
1571     pui8Dest[0] = 0x01;
1572     pui8Dest[1] = ui32OpCode & 0xFF;
1573     pui8Dest[2] = (ui32OpCode >> 8) & 0xFF;
1574     pui8Dest[3] = (ui32TotalLength - 4) & 0xFF;
1575 
1576     //
1577     // Finish filling the array with any parameters that may be required.
1578     //
1579     for (uint32_t i = 4; i < ui32TotalLength; i++)
1580     {
1581         pui8Dest[i] = pui8Parameters[i - 4];
1582     }
1583 
1584     //
1585     // Return the status.
1586     //
1587     return AM_HAL_STATUS_SUCCESS;
1588 } // am_hal_ble_vs_command_build()
1589 
1590 //*****************************************************************************
1591 //
1592 // Returns the number of bytes written.
1593 //
1594 //*****************************************************************************
1595 uint32_t
am_hal_ble_blocking_hci_write(void * pHandle,uint8_t ui8Type,uint32_t * pui32Data,uint32_t ui32NumBytes)1596 am_hal_ble_blocking_hci_write(void *pHandle, uint8_t ui8Type,
1597                               uint32_t *pui32Data, uint32_t ui32NumBytes)
1598 {
1599     uint32_t ui32ErrorStatus;
1600 
1601     am_hal_ble_transfer_t HciWrite =
1602     {
1603         .pui32Data = pui32Data,
1604         .pui8Offset = {ui8Type, 0x0, 0x0},
1605         .ui8OffsetLen = 0,
1606         .ui16Length = ui32NumBytes,
1607         .ui8Command = AM_HAL_BLE_WRITE,
1608         .ui8RepeatCount = 0,
1609         .bContinue = false,
1610         .pfnTransferCompleteCB = 0x0,
1611         .pvContext = 0x0,
1612     };
1613 
1614     //
1615     // Check the handle.
1616     //
1617     if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
1618     {
1619         return 0;
1620     }
1621 
1622     //
1623     // Fix up the offset length based on the packet type, and send the bytes.
1624     //
1625     if (ui8Type != AM_HAL_BLE_RAW)
1626     {
1627         HciWrite.ui8OffsetLen = 1;
1628     }
1629 
1630     ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &HciWrite);
1631     if (ui32ErrorStatus != AM_HAL_STATUS_SUCCESS)
1632     {
1633         return ui32ErrorStatus;
1634     }
1635 
1636     return AM_HAL_STATUS_SUCCESS;
1637 } // am_hal_ble_blocking_hci_write()
1638 
1639 //*****************************************************************************
1640 //
1641 // Returns the number of bytes received.
1642 //
1643 //*****************************************************************************
1644 uint32_t
am_hal_ble_blocking_hci_read(void * pHandle,uint32_t * pui32Data,uint32_t * pui32BytesReceived)1645 am_hal_ble_blocking_hci_read(void *pHandle, uint32_t *pui32Data, uint32_t *pui32BytesReceived)
1646 {
1647     uint32_t ui32Module, ui32NumBytes, ui32ErrorStatus;
1648 
1649     am_hal_ble_buffer(2) sLengthBytes;
1650 
1651     am_hal_ble_transfer_t HciRead =
1652     {
1653         .pui32Data = sLengthBytes.words,
1654         .pui8Offset = {0x0, 0x0, 0x0},
1655         .ui8OffsetLen = 0,
1656         .ui16Length = 2,
1657         .ui8Command = AM_HAL_BLE_READ,
1658         .ui8RepeatCount = 0,
1659         .bContinue = false,
1660         .pfnTransferCompleteCB = 0x0,
1661         .pvContext = 0x0,
1662     };
1663 
1664     //
1665     // Check the handle.
1666     //
1667     if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
1668     {
1669         return 0;
1670     }
1671 
1672     //
1673     // Handle is good, so get the module number.
1674     //
1675     ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
1676 
1677     //
1678     // Make sure the IRQ signal is set.
1679     //
1680     if ( BLEIFn(ui32Module)->BSTATUS_b.BLEIRQ )
1681     {
1682         //
1683         // Read the length bytes.
1684         //
1685         ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &HciRead);
1686         if ( ui32ErrorStatus != AM_HAL_STATUS_SUCCESS)
1687         {
1688             return ui32ErrorStatus;
1689         }
1690 
1691         //
1692         // Read the rest of the packet.
1693         //
1694         HciRead.pui32Data = pui32Data;
1695         HciRead.ui16Length = (sLengthBytes.bytes[0] +
1696                               (sLengthBytes.bytes[1] << 8));
1697 
1698         //
1699         // Check if the length is not out of the boundary
1700         //
1701         if ( (HciRead.ui16Length == 0) || (HciRead.ui16Length > 256) )
1702         {
1703             return AM_HAL_STATUS_OUT_OF_RANGE;
1704         }
1705 
1706         ui32ErrorStatus = am_hal_ble_blocking_transfer(pHandle, &HciRead);
1707         if ( ui32ErrorStatus != AM_HAL_STATUS_SUCCESS)
1708         {
1709             return ui32ErrorStatus;
1710         }
1711 
1712         ui32NumBytes =  HciRead.ui16Length;
1713     }
1714     else
1715     {
1716         ui32NumBytes = 0;
1717     }
1718 
1719     if (pui32BytesReceived)
1720     {
1721         *pui32BytesReceived = ui32NumBytes;
1722     }
1723 
1724     return AM_HAL_STATUS_SUCCESS;
1725 } // am_hal_ble_blocking_hci_read()
1726 
1727 //*****************************************************************************
1728 //
1729 // Returns the number of bytes written.
1730 //
1731 //*****************************************************************************
1732 uint32_t
am_hal_ble_nonblocking_hci_write(void * pHandle,uint8_t ui8Type,uint32_t * pui32Data,uint32_t ui32NumBytes,am_hal_ble_transfer_complete_cb_t pfnCallback,void * pvContext)1733 am_hal_ble_nonblocking_hci_write(void *pHandle, uint8_t ui8Type,
1734                                  uint32_t *pui32Data, uint32_t ui32NumBytes,
1735                                  am_hal_ble_transfer_complete_cb_t pfnCallback,
1736                                  void *pvContext)
1737 {
1738     //
1739     // Check the handle.
1740     //
1741     if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
1742     {
1743         return 0;
1744     }
1745 
1746     am_hal_ble_transfer_t HciWrite =
1747     {
1748         .pui32Data = pui32Data,
1749         .pui8Offset = {ui8Type, 0x0, 0x0},
1750         .ui8OffsetLen = 0,
1751         .ui16Length = ui32NumBytes,
1752         .ui8Command = AM_HAL_BLE_WRITE,
1753         .ui8RepeatCount = 0,
1754         .bContinue = false,
1755         .pfnTransferCompleteCB = pfnCallback,
1756         .pvContext = pvContext,
1757     };
1758 
1759     //
1760     // Fix up the offset length based on the packet type, and send the bytes.
1761     //
1762     if (ui8Type != AM_HAL_BLE_RAW)
1763     {
1764         HciWrite.ui8OffsetLen = 1;
1765     }
1766 
1767     uint32_t ui32Status = am_hal_ble_nonblocking_transfer(pHandle, &HciWrite);
1768 
1769     return ui32Status;
1770 } // am_hal_ble_nonblocking_hci_write()
1771 
1772 //*****************************************************************************
1773 //
1774 // Returns the number of bytes received.
1775 //
1776 //*****************************************************************************
1777 uint32_t
am_hal_ble_nonblocking_hci_read(void * pHandle,uint32_t * pui32Data,am_hal_ble_transfer_complete_cb_t pfnCallback,void * pvContext)1778 am_hal_ble_nonblocking_hci_read(void *pHandle, uint32_t *pui32Data,
1779                                 am_hal_ble_transfer_complete_cb_t pfnCallback,
1780                                 void *pvContext)
1781 {
1782     uint32_t ui32Status;
1783     am_hal_ble_state_t *pBle = pHandle;
1784 
1785     am_hal_ble_buffer(2) sLengthBytes;
1786 
1787     am_hal_ble_transfer_t HciRead =
1788     {
1789         .pui32Data = sLengthBytes.words,
1790         .pui8Offset = {0x0, 0x0, 0x0},
1791         .ui8OffsetLen = 0,
1792         .ui16Length = 2,
1793         .ui8Command = AM_HAL_BLE_READ,
1794         .ui8RepeatCount = 0,
1795         .bContinue = false,
1796         .pfnTransferCompleteCB = pfnCallback,
1797         .pvContext = pvContext,
1798     };
1799 
1800     //
1801     // Check the handle.
1802     //
1803     if ( !AM_HAL_BLE_CHK_HANDLE(pHandle) )
1804     {
1805         return AM_HAL_STATUS_INVALID_HANDLE;
1806     }
1807 
1808     //
1809     // Make sure the IRQ signal is set.
1810     //
1811     if ( am_hal_ble_check_irq(pBle) )
1812     {
1813         //
1814         // Read the length bytes.
1815         //
1816         ui32Status = am_hal_ble_blocking_transfer(pHandle, &HciRead);
1817 
1818         if ( ui32Status != AM_HAL_STATUS_SUCCESS )
1819         {
1820             return ui32Status;
1821         }
1822 
1823         //
1824         // Read the rest of the packet.
1825         //
1826         HciRead.pfnTransferCompleteCB = pfnCallback;
1827         HciRead.pui32Data = pui32Data;
1828         HciRead.ui16Length = (sLengthBytes.bytes[0] +
1829                               (sLengthBytes.bytes[1] << 8));
1830 
1831         return am_hal_ble_nonblocking_transfer(pHandle, &HciRead);
1832     }
1833 
1834     //
1835     // If we get here, return fail.
1836     //
1837     return AM_HAL_STATUS_FAIL;
1838 } // am_hal_ble_nonblocking_hci_read()
1839 
1840 //*****************************************************************************
1841 //
1842 // Return true if BSTATUS is high.
1843 //
1844 //*****************************************************************************
1845 static bool
am_hal_ble_check_status(am_hal_ble_state_t * pBle)1846 am_hal_ble_check_status(am_hal_ble_state_t *pBle)
1847 {
1848     //
1849     // We need to make a special exception for "continue" packets, since the
1850     // BLE radio may deassert the STATUS signal mid-packet.
1851     //
1852     if (pBle->bContinuePacket)
1853     {
1854         pBle->bContinuePacket = false;
1855         return true;
1856     }
1857 
1858     if ( BLEIFn(0)->BSTATUS_b.SPISTATUS == 0)
1859     {
1860         return false;
1861     }
1862 
1863     return true;
1864 } // am_hal_ble_check_status()
1865 
1866 //*****************************************************************************
1867 //
1868 // Return true if IRQ is high.
1869 //
1870 //*****************************************************************************
1871 static bool
am_hal_ble_check_irq(am_hal_ble_state_t * pBle)1872 am_hal_ble_check_irq(am_hal_ble_state_t *pBle)
1873 {
1874     if ( BLEIFn(pBle->ui32Module)->BSTATUS_b.BLEIRQ )
1875     {
1876         return true;
1877     }
1878 
1879     return false;
1880 } // am_hal_ble_check_irq()
1881 
1882 //*****************************************************************************
1883 //
1884 // Blocking write to the BLE module.
1885 //
1886 //*****************************************************************************
1887 uint32_t
am_hal_ble_blocking_transfer(void * pHandle,am_hal_ble_transfer_t * psTransfer)1888 am_hal_ble_blocking_transfer(void *pHandle, am_hal_ble_transfer_t *psTransfer)
1889 {
1890     am_hal_ble_state_t *pBle = pHandle;
1891     uint32_t ui32IntEnable;
1892     uint32_t ui32Module;
1893 
1894     //
1895     // Check the handle.
1896     //
1897     if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
1898     {
1899         return AM_HAL_STATUS_INVALID_HANDLE;
1900     }
1901 
1902     //
1903     // Handle is good, so get the module number.
1904     //
1905     ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
1906 
1907     //
1908     // If the transfer doesn't have any bytes in it, just return success.
1909     //
1910     if (psTransfer->ui16Length == 0)
1911     {
1912         return AM_HAL_STATUS_SUCCESS;
1913     }
1914 
1915     //
1916     // Make sure we don't get any interrupts that might interfere with this
1917     // operation. We will save the interrupt enable register state so we can
1918     // restore it later. Also, make sure "command complete" is clear, so we can
1919     // detect the end of the transaction.
1920     //
1921     ui32IntEnable = BLEIFn(ui32Module)->INTEN;
1922     BLEIFn(ui32Module)->INTEN_b.BLECIRQ = 0;
1923     BLEIFn(ui32Module)->INTEN_b.BLECSSTAT = 0;
1924     BLEIFn(ui32Module)->INTEN_b.CMDCMP = 0;
1925     BLEIFn(ui32Module)->INTEN_b.THR = 0;
1926     BLEIFn(ui32Module)->INTCLR_b.CMDCMP = 1;
1927     BLEIFn(ui32Module)->INTCLR_b.BLECSSTAT = 1;
1928 
1929     //
1930     // If we're writing, we need to lock down the bus now. Set the wakeup
1931     // signal, and start monitoring STATUS. If STATUS isn't high within our
1932     // configured timeout, we have to assume that the BLE core is unresponsive
1933     // and report an error back to the caller.
1934     //
1935     if (psTransfer->ui8Command == AM_HAL_BLE_WRITE)
1936     {
1937         uint32_t ui32SpiStatus = false;
1938 
1939         if ( pBle->bLastPacketWasTX == true)
1940         {
1941             //
1942             // wait some time to give the controller more time to consume
1943             // the last TX packet
1944             //
1945             if (!pBle->bPatchComplete)
1946             {
1947                 delay_ms(3);
1948             }
1949             pBle->bLastPacketWasTX = false;
1950         }
1951 
1952         if (pBle->bPatchComplete)
1953         {
1954             uint32_t statusTimeout = 0;
1955             while (am_hal_ble_check_status(pBle) == true)
1956             {
1957                 statusTimeout++;
1958                 delay_us(10);
1959                 if (statusTimeout > 300)
1960                 {
1961                     break;
1962                 }
1963             }
1964         }
1965 
1966         //
1967         // Make sure the IO clock for the STATUS signal is on.
1968         //
1969         BLEIFn(0)->BLEDBG_b.IOCLKON = 1;
1970         delay_us(5);
1971 
1972         //
1973         // Set WAKE, and wait for a positive edge on the STATUS signal.
1974         //
1975         am_hal_ble_wakeup_set(pBle, 1);
1976 
1977         //
1978         // If we don't see an edge on STATUS in X ms, assume it's not coming
1979         // and return with an AM_HAL_BLE_STATUS_SPI_NOT_READY error.
1980         //
1981         uint32_t ui32Timeout = 0;
1982         uint32_t ui32TimeoutLimit = AM_BLE_STATUS_TIMEOUT;
1983 
1984         while (1)
1985         {
1986             if (am_hal_ble_check_status(pBle) == true)
1987             {
1988                 if (am_hal_ble_bus_lock(pBle))
1989                 {
1990                     ui32SpiStatus = AM_HAL_STATUS_SUCCESS;
1991                     break;
1992                 }
1993             }
1994             else if ((ui32Timeout >= ui32TimeoutLimit) ||
1995                      (BLEIFn(ui32Module)->BSTATUS_b.BLEIRQ))
1996             {
1997                 ui32SpiStatus = AM_HAL_BLE_STATUS_SPI_NOT_READY;
1998                 am_hal_ble_wakeup_set(pBle, 0);
1999                 break;
2000             }
2001 
2002             ui32Timeout++;
2003             delay_us(10);
2004         }
2005 
2006         //
2007         // Disable IOCLK
2008         //
2009         BLEIFn(0)->BLEDBG_b.IOCLKON = 0;
2010 
2011         if (ui32SpiStatus != AM_HAL_STATUS_SUCCESS)
2012         {
2013             //
2014             // Restore the interrupt state.
2015             //
2016             BLEIFn(ui32Module)->INTEN = ui32IntEnable;
2017             am_hal_ble_wakeup_set(pBle, 0);
2018             return ui32SpiStatus;
2019         }
2020     }
2021     else
2022     {
2023         if (BLEIFn(ui32Module)->BSTATUS_b.BLEIRQ == 0)
2024         {
2025             //
2026             // Restore the interrupt state.
2027             //
2028             BLEIFn(ui32Module)->INTEN = ui32IntEnable;
2029             return AM_HAL_BLE_STATUS_IRQ_LOW;
2030         }
2031 
2032         if (!am_hal_ble_bus_lock(pBle))
2033         {
2034             //
2035             // Restore the interrupt state.
2036             //
2037             BLEIFn(ui32Module)->INTEN = ui32IntEnable;
2038             return AM_HAL_BLE_STATUS_BUS_BUSY;
2039         }
2040     }
2041 
2042     if (psTransfer->bContinue)
2043     {
2044         pBle->bContinuePacket = true;
2045     }
2046 
2047     //
2048     // Set the current transfer, and clear the command complete interrupt so we
2049     // can tell when the next command completes.
2050     //
2051     memcpy(&pBle->sCurrentTransfer, psTransfer, sizeof(am_hal_ble_transfer_t));
2052 
2053     //
2054     // Critical section to protect the gap between command and data.
2055     //
2056     AM_CRITICAL_BEGIN;
2057 
2058     //
2059     // Write the command word.
2060     //
2061     am_hal_ble_cmd_write(pHandle, psTransfer);
2062 
2063     //
2064     // Now we need to manage the fifos based on the type of transfer. In either
2065     // case, we will keep draining or refilling the FIFO until the full
2066     // transaction is complete.
2067     //
2068     if (psTransfer->ui8Command == AM_HAL_BLE_WRITE)
2069     {
2070         bool bCmdCmp = false;
2071         uint32_t numWait = 0;
2072         // Adjust the byte count to be sent/received for repeat count
2073         uint32_t ui32Bytes = pBle->sCurrentTransfer.ui16Length;
2074 
2075         uint32_t ui32FifoRem;
2076         uint32_t *pui32Buffer = pBle->sCurrentTransfer.pui32Data;
2077 
2078         //
2079         // Write the command word.
2080         //
2081         am_hal_ble_cmd_write(pHandle, psTransfer);
2082 
2083         //
2084         // Keep looping until we're out of bytes to send or command complete (error).
2085         //
2086         while (ui32Bytes)
2087         {
2088             //
2089             // Limit the wait to reasonable limit - instead of blocking forever
2090             //
2091             numWait = 0;
2092             while ((ui32FifoRem = BLEIFn(ui32Module)->FIFOPTR_b.FIFO0REM) < 4)
2093             {
2094                 bCmdCmp = BLEIFn(ui32Module)->INTSTAT_b.CMDCMP;
2095                 if (bCmdCmp || (numWait++ >= AM_HAL_IOM_MAX_BLOCKING_WAIT))
2096                 {
2097                     //
2098                     // FIFO not expected to change any more - get out
2099                     //
2100                     break;
2101                 }
2102                 else
2103                 {
2104                     am_hal_flash_delay( FLASH_CYCLES_US(1) );
2105                 }
2106             }
2107             if (bCmdCmp || (ui32FifoRem < 4))
2108             {
2109                 //
2110                 // Something went wrong - bail out
2111                 //
2112                 break;
2113             }
2114 
2115             while ((ui32FifoRem >= 4) && ui32Bytes)
2116             {
2117                 BLEIFn(ui32Module)->FIFOPUSH = *pui32Buffer++;
2118                 ui32FifoRem -= 4;
2119                 if (ui32Bytes >= 4)
2120                 {
2121                     ui32Bytes -= 4;
2122                 }
2123                 else
2124                 {
2125                     ui32Bytes = 0;
2126                 }
2127             }
2128         }
2129        WHILE_TIMEOUT_MS_BREAK ( BLEIFn(ui32Module)->INTSTAT_b.CMDCMP == 0, 2,
2130                        AM_HAL_BLE_HCI_PACKET_INCOMPLETE );
2131        am_hal_ble_wakeup_set(pBle, 0);
2132     }
2133     else
2134     {
2135         while (pBle->ui32TransferIndex < pBle->sCurrentTransfer.ui16Length)
2136         {
2137             am_hal_ble_fifo_drain(pHandle);
2138         }
2139     }
2140 
2141     //
2142     // End the critical section.
2143     //
2144     AM_CRITICAL_END;
2145 
2146     //
2147     // Wait for the transaction to complete, and clear out any interrupts that
2148     // may have come up.
2149     //
2150     WHILE_TIMEOUT_MS ( BLEIFn(ui32Module)->INTSTAT_b.CMDCMP == 0, 10,
2151                        AM_HAL_BLE_HCI_PACKET_INCOMPLETE );
2152     BLEIFn(ui32Module)->INTCLR_b.CMDCMP = 1;
2153     BLEIFn(ui32Module)->INTCLR_b.THR = 1;
2154 
2155     //
2156     // Clear out the current transfer. We're done.
2157     //
2158     memset(&pBle->sCurrentTransfer, 0, sizeof(am_hal_ble_transfer_t));
2159     pBle->ui32TransferIndex = 0;
2160 
2161     //
2162     // Let the radio go back to sleep.
2163     //
2164     if (psTransfer->ui8Command == AM_HAL_BLE_WRITE)
2165     {
2166         am_hal_ble_wakeup_set(pBle, 0);
2167         pBle->bLastPacketWasTX = true;
2168     }
2169 
2170     if ((psTransfer->ui8Command == AM_HAL_BLE_READ) &&
2171         (pBle->bPatchComplete == true))
2172     {
2173         pBle->bLastPacketWasTX = false;
2174     }
2175 
2176     //
2177     // Restore the interrupt state.
2178     //
2179     BLEIFn(ui32Module)->INTEN = ui32IntEnable;
2180 
2181     //
2182     // Release the bus.
2183     //
2184     am_hal_ble_bus_release(pBle);
2185 
2186 
2187     //
2188     // Return the status.
2189     //
2190     return AM_HAL_STATUS_SUCCESS;
2191 } // am_hal_ble_blocking_transfer()
2192 
2193 //*****************************************************************************
2194 //
2195 // Nonblocking write to the BLE module.
2196 //
2197 //*****************************************************************************
2198 uint32_t
am_hal_ble_nonblocking_transfer(void * pHandle,am_hal_ble_transfer_t * psTransfer)2199 am_hal_ble_nonblocking_transfer(void *pHandle, am_hal_ble_transfer_t *psTransfer)
2200 {
2201     am_hal_ble_state_t *pBle = pHandle;
2202     uint32_t ui32Status;
2203 
2204     //
2205     // Check the handle.
2206     //
2207     if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
2208     {
2209         return AM_HAL_STATUS_INVALID_HANDLE;
2210     }
2211 
2212     //
2213     // Check to see if this is a write or a read.
2214     //
2215     if (psTransfer->ui8Command == AM_HAL_BLE_WRITE)
2216     {
2217         ui32Status = nonblocking_write(pBle, psTransfer);
2218     }
2219     else  // AM_HAL_BLE_READ case.
2220     {
2221         ui32Status = nonblocking_read(pBle, psTransfer);
2222     }
2223 
2224     return ui32Status;
2225 } // am_hal_ble_nonblocking_transfer()
2226 
2227 //*****************************************************************************
2228 //
2229 // Function for performing non-blocking writes to the HCI interface.
2230 //
2231 // This function will start a BLE write on the physical bus. The caller should
2232 // have already set WAKEUP and received a STATUS interrupt before they call
2233 // this function. When the write operation is complete, the MCU will receive a
2234 // command complete interrupt.
2235 //
2236 // Before calling this function, the caller is responsible for ensuring that
2237 // STATUS is high, that BLEIRQ is low, and the the bus isn't already in use. If
2238 // any of these problems exists when this function is called, it will simply
2239 // return with an error status.
2240 //
2241 //*****************************************************************************
2242 static uint32_t
nonblocking_write(am_hal_ble_state_t * pBle,am_hal_ble_transfer_t * psTransfer)2243 nonblocking_write(am_hal_ble_state_t *pBle, am_hal_ble_transfer_t *psTransfer)
2244 {
2245     uint32_t ui32Status = AM_HAL_STATUS_SUCCESS;
2246     uint32_t ui32Module = pBle->ui32Module;
2247 
2248     //
2249     // This function goes in a critical section to make sure that the operation
2250     // isn't interrupted or started again.
2251     //
2252     AM_CRITICAL_BEGIN;
2253 
2254     do
2255     {
2256         //
2257         // Check for any of the various reasons that we might not be able to
2258         // perform a write right now. If the bus is busy, if the BLE core requires
2259         // a READ operation, or if the BLE core simply isn't ready yet, stop here
2260         // and throw an error.
2261         //
2262         if ( pBle->bBusy )
2263         {
2264             ui32Status = AM_HAL_BLE_STATUS_BUS_BUSY;
2265             break;
2266         }
2267 
2268         if ( am_hal_ble_check_irq(pBle) )
2269         {
2270             ui32Status = AM_HAL_BLE_REQUESTING_READ;
2271             break;
2272         }
2273 
2274         if ( !am_hal_ble_check_status(pBle) )
2275         {
2276             ui32Status = AM_HAL_BLE_STATUS_SPI_NOT_READY;
2277             break;
2278         }
2279 
2280         if (psTransfer->ui16Length == 0)
2281         {
2282             ui32Status = AM_HAL_STATUS_SUCCESS;
2283             break;
2284         }
2285 
2286         //
2287         // With the obvious error cases out of the way, we can claim the bus and
2288         // start the transaction.
2289         //
2290         if ( pBle->bLastPacketWasTX == true )
2291         {
2292             delay_us(AM_BLE_TX_PACKET_SPACING_US);
2293         }
2294 
2295         pBle->bBusy = true;
2296         pBle->bLastPacketWasTX = true;
2297 
2298         //
2299         // Save the current transfer.
2300         //
2301         memcpy(&pBle->sCurrentTransfer, psTransfer, sizeof(am_hal_ble_transfer_t));
2302 
2303         //
2304         // Prepare the DMA.
2305         //
2306         BLEIFn(ui32Module)->DMATARGADDR = (uint32_t)pBle->sCurrentTransfer.pui32Data;
2307         BLEIFn(ui32Module)->DMATOTCOUNT = pBle->sCurrentTransfer.ui16Length;
2308         BLEIFn(ui32Module)->DMATRIGEN = BLEIF_DMATRIGEN_DTHREN_Msk;
2309         BLEIFn(ui32Module)->DMACFG =
2310             (_VAL2FLD(BLEIF_DMACFG_DMADIR, BLEIF_DMACFG_DMADIR_M2P) |
2311              _VAL2FLD(BLEIF_DMACFG_DMAPRI, BLEIF_DMACFG_DMAPRI_HIGH));
2312 
2313         //
2314         // Write the command word, and enable the DMA.
2315         //
2316         ui32Status = am_hal_ble_cmd_write(pBle, &pBle->sCurrentTransfer);
2317 
2318         BLEIFn(ui32Module)->DMACFG |= _VAL2FLD(BLEIF_DMACFG_DMAEN, BLEIF_DMACFG_DMAEN_EN);
2319 
2320         //
2321         // Make sure WAKE goes low as quickly as possible after starting the write.
2322         //
2323         if (ui32Status == AM_HAL_STATUS_SUCCESS)
2324         {
2325             am_hal_ble_wakeup_set(pBle, 0);
2326         }
2327     }
2328     while (0);
2329 
2330     //
2331     // No matter what happened above, the function should end here. We'll end
2332     // the critical section and alert the caller of our status.
2333     //
2334     AM_CRITICAL_END;
2335     return ui32Status;
2336 } // nonblocking_write()
2337 
2338 //*****************************************************************************
2339 //
2340 // This function performs a nonblocking read from the BLE core.
2341 //
2342 //*****************************************************************************
2343 static uint32_t
nonblocking_read(am_hal_ble_state_t * pBle,am_hal_ble_transfer_t * psTransfer)2344 nonblocking_read(am_hal_ble_state_t *pBle, am_hal_ble_transfer_t *psTransfer)
2345 {
2346     uint32_t ui32Status = AM_HAL_STATUS_SUCCESS;
2347     uint32_t ui32Module = pBle->ui32Module;
2348 
2349     //
2350     // This function goes in a critical section to make sure that the operation
2351     // isn't interrupted or started again.
2352     //
2353     AM_CRITICAL_BEGIN;
2354 
2355     do
2356     {
2357         if ( pBle->bBusy )
2358         {
2359             ui32Status = AM_HAL_BLE_STATUS_BUS_BUSY;
2360             break;
2361         }
2362 
2363         if ( !am_hal_ble_check_irq(pBle) )
2364         {
2365             ui32Status = AM_HAL_BLE_STATUS_IRQ_LOW;
2366             break;
2367         }
2368 
2369         if (psTransfer->ui16Length == 0)
2370         {
2371             ui32Status = AM_HAL_STATUS_SUCCESS;
2372             break;
2373         }
2374 
2375         //
2376         // With the obvious error cases out of the way, we can claim the bus and
2377         // start the transaction.
2378         //
2379         if ( pBle->bLastPacketWasTX == true )
2380         {
2381             delay_us(AM_BLE_TX_PACKET_SPACING_US);
2382         }
2383 
2384         pBle->bBusy = true;
2385         pBle->bLastPacketWasTX = false;
2386 
2387         //
2388         // Set the current transfer.
2389         //
2390         memcpy(&pBle->sCurrentTransfer, psTransfer, sizeof(am_hal_ble_transfer_t));
2391 
2392         BLEIFn(ui32Module)->DMATARGADDR = (uint32_t) pBle->sCurrentTransfer.pui32Data;
2393         BLEIFn(ui32Module)->DMATOTCOUNT = pBle->sCurrentTransfer.ui16Length;
2394         BLEIFn(ui32Module)->DMATRIGEN = (BLEIF_DMATRIGEN_DTHREN_Msk | BLEIF_INTCLR_CMDCMP_Msk);
2395         BLEIFn(ui32Module)->DMACFG =
2396             (_VAL2FLD(BLEIF_DMACFG_DMADIR, BLEIF_DMACFG_DMADIR_P2M) |
2397              _VAL2FLD(BLEIF_DMACFG_DMAPRI, BLEIF_DMACFG_DMAPRI_HIGH));
2398 
2399         //
2400         // Write the command word, and enable the DMA.
2401         //
2402         ui32Status = am_hal_ble_cmd_write(pBle, &pBle->sCurrentTransfer);
2403         BLEIFn(ui32Module)->DMACFG |= _VAL2FLD(BLEIF_DMACFG_DMAEN, BLEIF_DMACFG_DMAEN_EN);
2404     }
2405     while (0);
2406 
2407     //
2408     // No matter what happened above, the function should end here. We'll end
2409     // the critical section and alert the caller of our status.
2410     //
2411     AM_CRITICAL_END;
2412     return ui32Status;
2413 } // nonblocking_read()
2414 
2415 //*****************************************************************************
2416 //
2417 // Mark the BLE interface busy so it doesn't get used by more than one
2418 // interface.
2419 //
2420 //*****************************************************************************
2421 static bool
am_hal_ble_bus_lock(am_hal_ble_state_t * pBle)2422 am_hal_ble_bus_lock(am_hal_ble_state_t *pBle)
2423 {
2424     bool bLockObtained;
2425 
2426     //
2427     // In one atomic sweep, check to see if the bus is busy, and reserve it if
2428     // it isn't.
2429     //
2430     AM_CRITICAL_BEGIN;
2431 
2432     if (pBle->bBusy == false)
2433     {
2434         am_hal_debug_gpio_set(BLE_DEBUG_TRACE_11);
2435         pBle->bBusy = true;
2436         bLockObtained = true;
2437         pBle->bCmdComplete = 0;
2438         pBle->bDmaComplete = 0;
2439         pBle->bFlowControlComplete = 0;
2440     }
2441     else
2442     {
2443         bLockObtained = false;
2444     }
2445 
2446     AM_CRITICAL_END;
2447 
2448     //
2449     // Tell the caller if we successfully locked the bus.
2450     //
2451     return bLockObtained;
2452 } // am_hal_ble_bus_lock()
2453 
2454 //*****************************************************************************
2455 //
2456 // Release the bus so someone else can use it.
2457 //
2458 //*****************************************************************************
2459 static void
am_hal_ble_bus_release(am_hal_ble_state_t * pBle)2460 am_hal_ble_bus_release(am_hal_ble_state_t *pBle)
2461 {
2462     pBle->bBusy = false;
2463     am_hal_debug_gpio_clear(BLE_DEBUG_TRACE_11);
2464 }
2465 
2466 //*****************************************************************************
2467 //
2468 // Pull data out of the fifo for reads.
2469 //
2470 //*****************************************************************************
2471 static uint32_t
am_hal_ble_fifo_drain(void * pHandle)2472 am_hal_ble_fifo_drain(void *pHandle)
2473 {
2474     uint32_t ui32Module;
2475     uint32_t ui32ReadSize, ui32RxDataLen, ui32BytesLeft;
2476     uint32_t *pDest;
2477 
2478     //
2479     // Check the handle.
2480     //
2481     if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
2482     {
2483         return 0;
2484     }
2485 
2486     //
2487     // Handle is good, so get the module number.
2488     //
2489     ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
2490 
2491     //
2492     // Rename some pointers for convenience.
2493     //
2494     am_hal_ble_state_t *pBle = pHandle;
2495     am_hal_ble_transfer_t *pTransfer = &pBle->sCurrentTransfer;
2496 
2497     //
2498     // Check to see how much data there is in the FIFO, and also how many
2499     // bytes are remaining in the transfer.
2500     //
2501     ui32RxDataLen = BLEIFn(ui32Module)->FIFOPTR_b.FIFO1SIZ;
2502     ui32BytesLeft = (pTransfer->ui16Length - pBle->ui32TransferIndex);
2503 
2504     //
2505     // Calculate how much we can drain the fifo.
2506     //
2507     if (ui32RxDataLen < 4)
2508     {
2509         return 0;
2510     }
2511     else if (ui32RxDataLen >= pTransfer->ui16Length)
2512     {
2513         ui32ReadSize = ui32BytesLeft;
2514     }
2515     else
2516     {
2517         ui32ReadSize = ui32RxDataLen & (~0x3);
2518     }
2519 
2520     //
2521     // Calculate the place where we last left off, feed the FIFO starting from
2522     // that location, and update the index to match.
2523     //
2524     pDest = &pTransfer->pui32Data[pBle->ui32TransferIndex / 4];
2525 
2526     am_hal_ble_fifo_read(pHandle, pDest, ui32ReadSize);
2527 
2528     pBle->ui32TransferIndex += ui32ReadSize;
2529 
2530     //
2531     // Return the number of bytes we wrote.
2532     //
2533     return ui32ReadSize;
2534 } // am_hal_ble_fifo_drain()
2535 
2536 //*****************************************************************************
2537 //
2538 // Write the command word for a BLE transfer.
2539 //
2540 //*****************************************************************************
2541 uint32_t
am_hal_ble_cmd_write(void * pHandle,am_hal_ble_transfer_t * psTransfer)2542 am_hal_ble_cmd_write(void *pHandle, am_hal_ble_transfer_t *psTransfer)
2543 {
2544     uint32_t ui32CmdWord, ui32OffsetHigh;
2545     uint32_t ui32Module;
2546 
2547     //
2548     // Check the handle.
2549     //
2550     if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
2551     {
2552         return AM_HAL_STATUS_INVALID_HANDLE;
2553     }
2554 
2555     //
2556     // Handle is good, so get the module number.
2557     //
2558     ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
2559 
2560     //
2561     // Figure out the command word and the offset register. Then write them.
2562     //
2563     switch (psTransfer->ui8OffsetLen)
2564     {
2565         case 0:
2566             ui32CmdWord = 0;
2567             ui32OffsetHigh = 0;
2568             break;
2569 
2570         case 1:
2571             ui32CmdWord = _VAL2FLD(BLEIF_CMD_OFFSETLO, psTransfer->pui8Offset[0]);
2572             ui32OffsetHigh = 0;
2573             break;
2574 
2575         case 2:
2576             ui32CmdWord = _VAL2FLD(BLEIF_CMD_OFFSETLO, psTransfer->pui8Offset[1]);
2577             ui32OffsetHigh = psTransfer->pui8Offset[0];
2578             break;
2579 
2580         case 3:
2581             ui32CmdWord = _VAL2FLD(BLEIF_CMD_OFFSETLO, psTransfer->pui8Offset[2]);
2582             ui32OffsetHigh = ((psTransfer->pui8Offset[1]) |
2583                               (psTransfer->pui8Offset[0] << 8));
2584             break;
2585 
2586         default:
2587             // Offset length was incorrect.
2588             return AM_HAL_STATUS_INVALID_ARG;
2589     }
2590 
2591     ui32CmdWord |= (_VAL2FLD(BLEIF_CMD_OFFSETCNT, psTransfer->ui8OffsetLen) |
2592                     _VAL2FLD(BLEIF_CMD_TSIZE, psTransfer->ui16Length)       |
2593                     _VAL2FLD(BLEIF_CMD_CONT, psTransfer->bContinue)         |
2594                     psTransfer->ui8Command);
2595 
2596     BLEIFn(ui32Module)->OFFSETHI = ui32OffsetHigh;
2597     BLEIFn(ui32Module)->CMD = ui32CmdWord;
2598 
2599     //
2600     // Return the status.
2601     //
2602     return AM_HAL_STATUS_SUCCESS;
2603 } // am_hal_ble_cmd_write()
2604 
2605 //*****************************************************************************
2606 //
2607 // Read ui32NumBytes from the RX FIFO.
2608 //
2609 //*****************************************************************************
2610 static void
am_hal_ble_fifo_read(void * pHandle,uint32_t * pui32Data,uint32_t ui32NumBytes)2611 am_hal_ble_fifo_read(void *pHandle, uint32_t *pui32Data, uint32_t ui32NumBytes)
2612 {
2613     uint32_t ui32Index;
2614     uint32_t ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
2615 
2616     for (ui32Index = 0; (ui32Index * 4) < ui32NumBytes; ui32Index++)
2617     {
2618         pui32Data[ui32Index] = BLEIFn(ui32Module)->FIFOPOP;
2619 
2620 #ifndef AM_HAL_BLE_NO_FIFO_PROTECTION
2621         BLEIFn(ui32Module)->FIFOPOP = 0;
2622 #endif
2623 
2624     }
2625 } // am_hal_ble_fifo_read()
2626 
2627 //*****************************************************************************
2628 //
2629 // Call the appropriate callbacks when DMA transfers complete.
2630 //
2631 //*****************************************************************************
2632 uint32_t
am_hal_ble_int_service(void * pHandle,uint32_t ui32Status)2633 am_hal_ble_int_service(void *pHandle, uint32_t ui32Status)
2634 {
2635     am_hal_ble_state_t *pBle = pHandle;
2636     uint32_t ui32Module;
2637 
2638     //
2639     // Check the handle.
2640     //
2641     if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
2642     {
2643         return AM_HAL_STATUS_INVALID_HANDLE;
2644     }
2645 
2646     //
2647     // The handle is good, so get the module number.
2648     //
2649     ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
2650 
2651     //
2652     // Track each of the interrupts signaling the end of an HCI transfer.
2653     //
2654     if ( ui32Status & BLEIF_INTSTAT_CMDCMP_Msk )
2655     {
2656         pBle->bCmdComplete = true;
2657     }
2658 
2659     if ( ui32Status & BLEIF_INTSTAT_DCMP_Msk )
2660     {
2661         pBle->bDmaComplete = true;
2662     }
2663 
2664     //
2665     // For B0 parts, we can detect when key flow control signals from the BLE
2666     // core are de-asserted.
2667     //
2668     if (APOLLO3_B0 || APOLLO3_GE_B0)
2669     {
2670         //
2671         // Check for falling IRQ
2672         //
2673         if ( (ui32Status & BLEIF_INTSTAT_BLECIRQN_Msk)  &&
2674              (pBle->sCurrentTransfer.ui8Command == AM_HAL_BLE_READ) )
2675         {
2676             pBle->bFlowControlComplete = true;
2677         }
2678 
2679         //
2680         // Check for falling status.
2681         //
2682         if ( (ui32Status & BLEIF_INTSTAT_BLECSSTATN_Msk ) &&
2683              (pBle->sCurrentTransfer.ui8Command == AM_HAL_BLE_WRITE) )
2684         {
2685             pBle->bFlowControlComplete = true;
2686         }
2687     }
2688     else
2689     {
2690         return AM_HAL_STATUS_FAIL;
2691     }
2692 
2693     //
2694     // If we get a command complete, we need to release the wake signal,
2695     // disable the DMA, release the bus, and call any callback that might
2696     // exist.
2697     //
2698     // For revision A parts, "command complete" means that the DMA operation
2699     // and the BLE SPI interface have both finished their operations. For rev B
2700     // parts, we will also wait for the flow control signal (either STATUS or
2701     // IRQ) to be removed.
2702     //
2703     if ( pBle->bCmdComplete && pBle->bDmaComplete &&
2704          ((pBle->bFlowControlComplete) || (!APOLLO3_GE_B0) || SKIP_FALLING_EDGES) )
2705     {
2706         //
2707         // Clean up our state flags.
2708         //
2709         pBle->bCmdComplete = false;
2710         pBle->bDmaComplete = false;
2711         pBle->bFlowControlComplete = false;
2712 
2713         //
2714         // If our FIFOs aren't empty right now, either the DMA didn't finish,
2715         // or this interrupt handler is somehow being called incorrectly.
2716         //
2717         if ( BLEIFn(ui32Module)->FIFOPTR != 0x20002000 )
2718         {
2719             return AM_HAL_BLE_FIFO_ERROR;
2720         }
2721 
2722         //
2723         // Drop the wake request if we had one, and make sure we remember if
2724         // the last packet was a transmit packet.
2725         //
2726         if ((pBle->sCurrentTransfer.ui8Command == AM_HAL_BLE_WRITE) &&
2727             (pBle->bPatchComplete == true))
2728         {
2729             pBle->bLastPacketWasTX = true;
2730             am_hal_ble_wakeup_set(pBle, 0);
2731         }
2732 
2733         //
2734         // If this was a read packet, remember that it wasn't a TX packet.
2735         //
2736         if (pBle->sCurrentTransfer.ui8Command == AM_HAL_BLE_READ)
2737         {
2738             pBle->bLastPacketWasTX = false;
2739         }
2740 
2741         //
2742         // Disable the DMA
2743         //
2744         BLEIFn(ui32Module)->DMACFG = 0;
2745 
2746         am_hal_ble_bus_release(pBle);
2747 
2748         if ( pBle->sCurrentTransfer.pfnTransferCompleteCB )
2749         {
2750             am_hal_ble_transfer_complete_cb_t pfnCallback;
2751             uint32_t ui32Length;
2752             uint8_t *pui8Data;
2753             void *pvContext;
2754 
2755             pfnCallback = pBle->sCurrentTransfer.pfnTransferCompleteCB;
2756             pui8Data = (uint8_t * ) pBle->sCurrentTransfer.pui32Data;
2757             ui32Length = pBle->sCurrentTransfer.ui16Length;
2758             pvContext = pBle->sCurrentTransfer.pvContext;
2759 
2760             pfnCallback(pui8Data, ui32Length, pvContext);
2761         }
2762     }
2763 
2764     //
2765     // Return the status.
2766     //
2767     return AM_HAL_STATUS_SUCCESS;
2768 } // am_hal_ble_int_service()
2769 
2770 //*****************************************************************************
2771 //
2772 // Interrupt Enable
2773 //
2774 //*****************************************************************************
2775 uint32_t
am_hal_ble_int_enable(void * pHandle,uint32_t ui32InterruptMask)2776 am_hal_ble_int_enable(void *pHandle, uint32_t ui32InterruptMask)
2777 {
2778     uint32_t ui32Module;
2779 
2780     //
2781     // Check the handle.
2782     //
2783     if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
2784     {
2785         return AM_HAL_STATUS_INVALID_HANDLE;
2786     }
2787 
2788     //
2789     // Handle is good, so get the module number.
2790     //
2791     ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
2792 
2793     AM_CRITICAL_BEGIN
2794     BLEIFn(ui32Module)->INTEN |= ui32InterruptMask;
2795     AM_CRITICAL_END
2796 
2797     //
2798     // Return the status.
2799     //
2800     return AM_HAL_STATUS_SUCCESS;
2801 } // am_hal_ble_int_enable()
2802 
2803 //*****************************************************************************
2804 //
2805 // Interrupt Enable
2806 //
2807 //*****************************************************************************
2808 uint32_t
am_hal_ble_int_disable(void * pHandle,uint32_t ui32InterruptMask)2809 am_hal_ble_int_disable(void *pHandle, uint32_t ui32InterruptMask)
2810 {
2811     uint32_t ui32Module;
2812 
2813     //
2814     // Check the handle.
2815     //
2816     if (!AM_HAL_BLE_CHK_HANDLE(pHandle))
2817     {
2818         return AM_HAL_STATUS_INVALID_HANDLE;
2819     }
2820 
2821     //
2822     // Handle is good, so get the module number.
2823     //
2824     ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
2825 
2826     AM_CRITICAL_BEGIN
2827     BLEIFn(ui32Module)->INTEN &= ~ui32InterruptMask;
2828     AM_CRITICAL_END
2829 
2830     //
2831     // Return the status.
2832     //
2833     return AM_HAL_STATUS_SUCCESS;
2834 } // am_hal_ble_int_disable()
2835 
2836 //*****************************************************************************
2837 //
2838 // Check the status of the interrupts.
2839 //
2840 //*****************************************************************************
2841 uint32_t
am_hal_ble_int_status(void * pHandle,bool bEnabledOnly)2842 am_hal_ble_int_status(void *pHandle, bool bEnabledOnly)
2843 {
2844     uint32_t ui32Module = ((am_hal_ble_state_t *) pHandle)->ui32Module;
2845 
2846     if (bEnabledOnly)
2847     {
2848         uint32_t ui32IntEn = BLEIFn(ui32Module)->INTEN;
2849         return ( BLEIFn(ui32Module)->INTSTAT & ui32IntEn );
2850     }
2851     else
2852     {
2853         return BLEIFn(ui32Module)->INTSTAT;
2854     }
2855 } // am_hal_ble_int_status()
2856 
2857 //*****************************************************************************
2858 //
2859 // Clear the interrupt status.
2860 //
2861 //*****************************************************************************
2862 uint32_t
am_hal_ble_int_clear(void * pHandle,uint32_t ui32InterruptMask)2863 am_hal_ble_int_clear(void *pHandle, uint32_t ui32InterruptMask)
2864 {
2865     uint32_t ui32Module;
2866 
2867     //
2868     // Check the handle.
2869     //
2870     if ( !AM_HAL_BLE_CHK_HANDLE(pHandle) )
2871     {
2872         return AM_HAL_STATUS_INVALID_HANDLE;
2873     }
2874 
2875     //
2876     // Handle is good, so get the module number.
2877     //
2878     ui32Module = ((am_hal_ble_state_t *)pHandle)->ui32Module;
2879 
2880     BLEIFn(ui32Module)->INTCLR = ui32InterruptMask;
2881 
2882     //
2883     // Return the status.
2884     //
2885     return AM_HAL_STATUS_SUCCESS;
2886 } // am_hal_ble_int_clear()
2887 
2888 //*****************************************************************************
2889 //
2890 // check 32768Hz clock is ready.
2891 //
2892 //*****************************************************************************
2893 uint32_t
am_hal_ble_check_32k_clock(void * pHandle)2894 am_hal_ble_check_32k_clock(void *pHandle)
2895 {
2896     am_hal_ble_state_t *pBLE = pHandle;
2897     uint32_t rc32k_clock = 0xFFFFFFFF;
2898 
2899     if (APOLLO3_B0)
2900     {
2901         am_hal_ble_plf_reg_read(pBLE, AM_HAL_BLE_IP_RAM_32K_CLOCK_ADDR_B0, &rc32k_clock);
2902     }
2903     else
2904     {
2905         am_hal_ble_plf_reg_read(pBLE, AM_HAL_BLE_IP_RAM_32K_CLOCK_ADDR_A1, &rc32k_clock);
2906     }
2907 
2908     // Normal 32KHz clock is about 0x8000
2909     if ( (rc32k_clock > 0x8200) || (rc32k_clock < 0x7B00) )
2910     {
2911         return AM_HAL_STATUS_FAIL;
2912     }
2913     else
2914     {
2915         return AM_HAL_STATUS_SUCCESS;
2916     }
2917 } // am_hal_ble_check_32k_clock()
2918 
2919 //*****************************************************************************
2920 //
2921 // Read a register value from the BLE core.
2922 //
2923 //*****************************************************************************
2924 uint32_t
am_hal_ble_plf_reg_read(void * pHandle,uint32_t ui32Address,uint32_t * pui32Value)2925 am_hal_ble_plf_reg_read(void *pHandle, uint32_t ui32Address, uint32_t *pui32Value)
2926 {
2927     am_hal_ble_state_t *pBLE = pHandle;
2928     uint8_t pui8Parameter[4];
2929     uint32_t ui32IntEnable;
2930 
2931     uint32_t ui32Module = pBLE->ui32Module;
2932 
2933     //
2934     // Make a buffer big enough to hold the register write command, and a
2935     // second one big enough to hold the response.
2936     //
2937     am_hal_ble_buffer(AM_HAL_BLE_PLF_REGISTER_READ_LENGTH) sWriteCommand;
2938     am_hal_ble_buffer(32) sResponse;
2939 
2940     //
2941     // Prepare our register write value.
2942     //
2943     pui8Parameter[0] = ui32Address;
2944     pui8Parameter[1] = (ui32Address >> 8);
2945     pui8Parameter[2] = (ui32Address >> 16);
2946     pui8Parameter[3] = (ui32Address >> 24);
2947 
2948     sResponse.words[0] = 0;
2949     sResponse.words[1] = 0;
2950     sResponse.words[2] = 0;
2951 
2952     //
2953     // Fill the buffer with the specific command we want to write, and send it.
2954     //
2955     am_hal_ble_vs_command_build(sWriteCommand.words,
2956                                 AM_HAL_BLE_PLF_REGISTER_READ_OPCODE,
2957                                 AM_HAL_BLE_PLF_REGISTER_READ_LENGTH,
2958                                 pui8Parameter);
2959 
2960     //
2961     // Temporarily disable BLE interrupts.
2962     //
2963     ui32IntEnable = BLEIFn(ui32Module)->INTEN;
2964     BLEIFn(ui32Module)->INTEN = 0;
2965 
2966     am_hal_ble_blocking_hci_write(pBLE,
2967                                   AM_HAL_BLE_RAW,
2968                                   sWriteCommand.words,
2969                                   AM_HAL_BLE_PLF_REGISTER_READ_LENGTH);
2970 
2971     //
2972     // Make sure the IO clock for the STATUS signal is on.
2973     //
2974     BLEIFn(ui32Module)->BLEDBG_b.IOCLKON = 1;
2975 
2976     //
2977     // Wait for the response, and return it to the caller via our variable.
2978     //
2979     WHILE_TIMEOUT_MS ( BLEIFn(ui32Module)->BSTATUS_b.BLEIRQ == 0, 500,
2980                        AM_HAL_BLE_NO_HCI_RESPONSE );
2981 
2982     am_hal_ble_blocking_hci_read(pBLE, sResponse.words, 0);
2983 
2984     *pui32Value = (((sResponse.words[1] & 0xFF000000) >> 24) |
2985                    ((sResponse.words[2] & 0x00FFFFFF) << 8));
2986 
2987     //
2988     // Re-enable BLE interrupts.
2989     //
2990     BLEIFn(ui32Module)->INTCLR = ui32IntEnable;
2991     BLEIFn(ui32Module)->INTEN = ui32IntEnable;
2992 
2993     return AM_HAL_STATUS_SUCCESS;
2994 
2995 } // am_hal_ble_plf_reg_read()
2996 
2997 //*****************************************************************************
2998 //
2999 // Write a register value to the BLE core.
3000 //
3001 //*****************************************************************************
3002 uint32_t
am_hal_ble_plf_reg_write(void * pHandle,uint32_t ui32Address,uint32_t ui32Value)3003 am_hal_ble_plf_reg_write(void *pHandle, uint32_t ui32Address, uint32_t ui32Value)
3004 {
3005     am_hal_ble_state_t *pBLE = pHandle;
3006     uint8_t pui8Parameter[8];
3007     uint32_t ui32IntEnable;
3008 
3009     uint32_t ui32Module = pBLE->ui32Module;
3010 
3011     //
3012     // Make a buffer big enough to hold the register write command, and a
3013     // second one big enough to hold the response.
3014     //
3015     am_hal_ble_buffer(AM_HAL_BLE_PLF_REGISTER_WRITE_LENGTH) sWriteCommand;
3016     am_hal_ble_buffer(16) sResponse;
3017 
3018     //
3019     // Prepare our register write value.
3020     //
3021     pui8Parameter[0] = ui32Address;
3022     pui8Parameter[1] = (ui32Address >> 8);
3023     pui8Parameter[2] = (ui32Address >> 16);
3024     pui8Parameter[3] = (ui32Address >> 24);
3025     pui8Parameter[4] = ui32Value;
3026     pui8Parameter[5] = (ui32Value >> 8);
3027     pui8Parameter[6] = (ui32Value >> 16);
3028     pui8Parameter[7] = (ui32Value >> 24);
3029 
3030     //
3031     // Fill the buffer with the specific command we want to write, and send it.
3032     //
3033     am_hal_ble_vs_command_build(sWriteCommand.words,
3034                                 AM_HAL_BLE_PLF_REGISTER_WRITE_OPCODE,
3035                                 AM_HAL_BLE_PLF_REGISTER_WRITE_LENGTH,
3036                                 pui8Parameter);
3037 
3038     //
3039     // Temporarily disable BLE interrupts.
3040     //
3041     ui32IntEnable = BLEIFn(ui32Module)->INTEN;
3042     BLEIFn(ui32Module)->INTEN = 0;
3043 
3044     am_hal_ble_blocking_hci_write(pBLE,
3045                                   AM_HAL_BLE_RAW,
3046                                   sWriteCommand.words,
3047                                   AM_HAL_BLE_PLF_REGISTER_WRITE_LENGTH);
3048 
3049     //
3050     // Make sure the IO clock for the STATUS signal is on.
3051     //
3052     BLEIFn(ui32Module)->BLEDBG_b.IOCLKON = 1;
3053 
3054     //
3055     // Wait for the response.
3056     //
3057     WHILE_TIMEOUT_MS ( BLEIFn(ui32Module)->BSTATUS_b.BLEIRQ == 0, 50,
3058                        AM_HAL_BLE_NO_HCI_RESPONSE );
3059 
3060     am_hal_ble_blocking_hci_read(pBLE, sResponse.words, 0);
3061 
3062     //
3063     // Re-enable BLE interrupts.
3064     //
3065     BLEIFn(ui32Module)->INTCLR = ui32IntEnable;
3066     BLEIFn(ui32Module)->INTEN = ui32IntEnable;
3067 
3068     return AM_HAL_STATUS_SUCCESS;
3069 
3070 } // am_hal_ble_plf_reg_write()
3071 
3072 //*****************************************************************************
3073 //
3074 // Set the modulation frequency offset from INFO1,
3075 // based on the tested values stored in non-volatile memory.
3076 //
3077 //*****************************************************************************
3078 uint32_t
am_hal_ble_load_modex_trim_set(void * pHandle)3079 am_hal_ble_load_modex_trim_set(void *pHandle)
3080 {
3081     uint8_t ui8TrimValue;
3082     //
3083     // load the modex trim data from info1.
3084     //
3085     ui8TrimValue = am_hal_ble_read_trimdata_from_info1();
3086     if ( ui8TrimValue )
3087     {
3088         am_hal_ble_transmitter_modex_set(pHandle, ui8TrimValue);
3089         return AM_HAL_STATUS_SUCCESS;
3090     }
3091     else
3092     {
3093         return AM_HAL_STATUS_FAIL;
3094     }
3095 } // am_hal_ble_load_modex_trim_set()
3096 
3097 //*****************************************************************************
3098 //
3099 // Load the modulation frequency offset from INFO1,
3100 // based on the tested values stored in non-volatile memory.
3101 //
3102 //*****************************************************************************
3103 uint8_t
am_hal_ble_read_trimdata_from_info1(void)3104 am_hal_ble_read_trimdata_from_info1(void)
3105 {
3106     uint32_t ui32TrimValue = 0, temp = 0;
3107     uint8_t TrimData = 0;
3108 
3109     temp = ui32TrimValue = AM_REGVAL(0x50023808);
3110     temp &= 0xffffff00;
3111 
3112     if ( temp == 0x18240600 )
3113     {
3114         TrimData = ui32TrimValue & 0xFF;
3115     }
3116     else
3117     {
3118         TrimData = 0;
3119     }
3120 
3121     if ( (TrimData > 0x50) || (TrimData < 0x20) )   // change from 0x40 to 0x50 for improving the FT2 yield.
3122     {
3123         TrimData = 0;
3124     }
3125 
3126     return TrimData;
3127 } // am_hal_ble_read_trimdata_from_info1()
3128 
3129 //*****************************************************************************
3130 //
3131 // Manually set modulation characteristic
3132 // based on the tested values at customer side.
3133 // manually set frequency offset for 10101010 or 01010101 pattern
3134 // parameter default value is 0x34, increase to get larger frequency offset
3135 //
3136 //*****************************************************************************
3137 uint32_t
am_hal_ble_transmitter_modex_set(void * pHandle,uint8_t ui8ModFrqOffset)3138 am_hal_ble_transmitter_modex_set(void *pHandle, uint8_t ui8ModFrqOffset)
3139 {
3140     am_hal_ble_state_t *pBLE = pHandle;
3141     uint32_t RegValueMCGR, RegValueBACKCR, RegValueSTCR, RegValueDACSPICR, temp = 0;
3142 
3143     ui8ModFrqOffset &= 0x7F;
3144 
3145     am_hal_ble_plf_reg_read(pBLE, 0x43000004, &RegValueMCGR);
3146 
3147     //
3148     // Unlock the BLE registers.
3149     //
3150     am_hal_ble_plf_reg_write(pBLE, 0x43000004, 0xFFFFFFFF);
3151     am_hal_ble_plf_reg_read(pBLE, 0x52000008, &temp);
3152     temp |= 0x08;
3153     am_hal_ble_plf_reg_read(pBLE, 0x52000000, &RegValueSTCR);
3154     RegValueSTCR |= (1 << 10);
3155     am_hal_ble_plf_reg_write(pBLE, 0x52000000, RegValueSTCR);
3156 
3157     am_hal_ble_plf_reg_read(pBLE, 0x45800070, &RegValueBACKCR);
3158     am_hal_ble_plf_reg_write(pBLE, 0x45800070, (RegValueBACKCR | 0x8));
3159     RegValueDACSPICR = (ui8ModFrqOffset << 1) | 0x1;
3160     am_hal_ble_plf_reg_write(pBLE, 0x52000014, RegValueDACSPICR);
3161 
3162     am_hal_ble_plf_reg_write(pBLE, 0x52000008, temp);
3163 
3164     if (APOLLO3_B0)
3165     {
3166         am_hal_ble_plf_reg_write(pBLE, AM_HAL_BLE_IP_RAM_MODEX_TRIM_ADDR_B0, ui8ModFrqOffset);
3167     }
3168     else
3169     {
3170         am_hal_ble_plf_reg_write(pBLE, AM_HAL_BLE_IP_RAM_MODEX_TRIM_ADDR_A1, ui8ModFrqOffset);
3171     }
3172     am_hal_ble_plf_reg_write(pBLE, 0x43000004, RegValueMCGR);
3173 
3174     return AM_HAL_STATUS_SUCCESS;
3175 } // am_hal_ble_transmitter_modex_set()
3176 
3177 //*****************************************************************************
3178 //
3179 // Set BLE sleep enable/disable for the BLE core.
3180 // enable = 'true' set sleep enable, enable = 'false' set sleep disable
3181 //
3182 //*****************************************************************************
3183 uint32_t
am_hal_ble_sleep_set(void * pHandle,bool enable)3184 am_hal_ble_sleep_set(void *pHandle, bool enable)
3185 {
3186     am_hal_ble_state_t *pBLE = pHandle;
3187     uint32_t sleepenable = 0;
3188 
3189     if (APOLLO3_B0)
3190     {
3191         am_hal_ble_plf_reg_read(pBLE, AM_HAL_BLE_IP_RAM_SLEEP_ENABLE_ADDR_B0, &sleepenable);
3192     }
3193     else
3194     {
3195         am_hal_ble_plf_reg_read(pBLE, AM_HAL_BLE_IP_RAM_SLEEP_ENABLE_ADDR_A1, &sleepenable);
3196     }
3197 
3198     sleepenable &= 0xffff0100;
3199 
3200     if ( enable )
3201     {
3202         sleepenable |= 0x0101;
3203     }
3204 
3205     if (APOLLO3_B0)
3206     {
3207         am_hal_ble_plf_reg_write(pBLE, AM_HAL_BLE_IP_RAM_SLEEP_ENABLE_ADDR_B0, sleepenable);
3208     }
3209     else
3210     {
3211         am_hal_ble_plf_reg_write(pBLE, AM_HAL_BLE_IP_RAM_SLEEP_ENABLE_ADDR_A1, sleepenable);
3212     }
3213 
3214     return AM_HAL_STATUS_SUCCESS;
3215 } // am_hal_ble_sleep_set()
3216 
3217 //*****************************************************************************
3218 //
3219 // Get current sleep enable status
3220 // return 'true'  = sleep enable , 'false' =  sleep disable
3221 //
3222 //*****************************************************************************
3223 bool
am_hal_ble_sleep_get(void * pHandle)3224 am_hal_ble_sleep_get(void *pHandle)
3225 {
3226     am_hal_ble_state_t *pBLE = pHandle;
3227     uint32_t sleepenable = 0;
3228 
3229     if (APOLLO3_B0)
3230     {
3231         am_hal_ble_plf_reg_read(pBLE, AM_HAL_BLE_IP_RAM_SLEEP_ENABLE_ADDR_B0, &sleepenable);
3232     }
3233     else
3234     {
3235         am_hal_ble_plf_reg_read(pBLE, AM_HAL_BLE_IP_RAM_SLEEP_ENABLE_ADDR_A1, &sleepenable);
3236     }
3237 
3238     if ( (sleepenable & 0xFFFF) > 0 )
3239     {
3240         return true;
3241     }
3242 
3243     return false;
3244 } // am_hal_ble_sleep_get()
3245 
3246 //*****************************************************************************
3247 //
3248 // set the tx power of BLE
3249 // values.
3250 // ui32TxPower: 0x04->-10dBm 0x05->-5dBm 0x08->0dBm 0x0F->3dBm
3251 //
3252 //*****************************************************************************
3253 uint32_t
am_hal_ble_tx_power_set(void * pHandle,uint8_t ui32TxPower)3254 am_hal_ble_tx_power_set(void *pHandle, uint8_t ui32TxPower)
3255 {
3256     am_hal_ble_state_t *pBLE = pHandle;
3257     uint32_t RegValueMCGR, tempreg = 0;
3258     uint32_t ui32PowerValue = 0x00000008;
3259     ui32PowerValue |= (ui32TxPower & 0xF) << 16;
3260 
3261     am_hal_ble_plf_reg_read(pBLE, 0x43000004, &RegValueMCGR);
3262 
3263     //
3264     // Unlock the BLE controller registers.
3265     //
3266     am_hal_ble_plf_reg_write(pBLE, 0x43000004, 0xFFFFFFFF);
3267 
3268     // set tx power register at 0x52400018
3269     am_hal_ble_plf_reg_write(pBLE, 0x52400018, ui32PowerValue);
3270 
3271     // Lock BLE controller registers
3272     am_hal_ble_plf_reg_write(pBLE, 0x43000004, RegValueMCGR);
3273 
3274     //
3275     // Update BLE controller RAM settings as well.
3276     // Note:
3277     //    Register values may be lost when BLE controller enters deepsleep.
3278     //    BLE controller loads RAM settings back upon wakeup.
3279     //    To retain the setting, BLE controller RAM settings should be updated.
3280     //
3281     if (APOLLO3_B0)
3282     {
3283         am_hal_ble_plf_reg_read(pBLE, AM_HAL_BLE_IP_RAM_POWER_LEVEL_ADDR_B0, &tempreg);
3284     }
3285     else
3286     {
3287         am_hal_ble_plf_reg_read(pBLE, AM_HAL_BLE_IP_RAM_POWER_LEVEL_ADDR_A1, &tempreg);
3288     }
3289 
3290     tempreg &= 0xffffff00;
3291     tempreg |= ui32TxPower;
3292 
3293     if (APOLLO3_B0)
3294     {
3295         am_hal_ble_plf_reg_write(pBLE, AM_HAL_BLE_IP_RAM_POWER_LEVEL_ADDR_B0, tempreg);
3296     }
3297     else
3298     {
3299         am_hal_ble_plf_reg_write(pBLE, AM_HAL_BLE_IP_RAM_POWER_LEVEL_ADDR_A1, tempreg);
3300     }
3301 
3302     return AM_HAL_STATUS_SUCCESS;
3303 } // am_hal_ble_tx_power_set()
3304 
3305 //*****************************************************************************
3306 //
3307 // End Doxygen group.
3308 //! @}
3309 //
3310 //*****************************************************************************
3311