1 /******************************************************************************
2  *
3  * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by
4  * Analog Devices, Inc.),
5  * Copyright (C) 2023-2024 Analog Devices, Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  ******************************************************************************/
20 
21 /* **** Includes **** */
22 #include <string.h>
23 #include "mxc_assert.h"
24 #include "mxc_sys.h"
25 #include "owm_reva.h"
26 
27 /* **** Definitions **** */
28 #define MXC_OWM_CLK_FREQ 1000000 //1-Wire requires 1MHz clock
29 
30 /* **** Globals **** */
31 static int LastDiscrepancy;
32 static int LastDeviceFlag;
33 
34 /* **** Functions **** */
35 static uint8_t CalculateCRC8(uint8_t *data, int len);
36 static uint8_t update_crc8(uint8_t crc, uint8_t value);
37 
38 /* ************************************************************************* */
MXC_OWM_RevA_Init(mxc_owm_reva_regs_t * owm,const mxc_owm_cfg_t * cfg)39 int MXC_OWM_RevA_Init(mxc_owm_reva_regs_t *owm, const mxc_owm_cfg_t *cfg)
40 {
41     uint32_t ext_pu_en = 0;
42 
43     // Select the PU mode and polarity based on cfg input
44     switch (cfg->ext_pu_mode) {
45     case MXC_OWM_EXT_PU_ACT_HIGH:
46         ext_pu_en = 1; // EXT_PULLUP_MODE_USED;
47         break;
48 
49     case MXC_OWM_EXT_PU_ACT_LOW:
50         ext_pu_en = 1; // EXT_PULLUP_MODE_USED;
51         break;
52 
53     case MXC_OWM_EXT_PU_UNUSED:
54         ext_pu_en = 0; // EXT_PULLUP_MODE_UNUSED;
55         break;
56 
57     default:
58         return E_BAD_PARAM;
59     }
60 
61     // Set owm internal clock divider
62     MXC_OWM_SystemClockUpdated();
63 
64     // Set configuration
65     owm->cfg = (((cfg->int_pu_en << MXC_F_OWM_REVA_CFG_INT_PULLUP_ENABLE_POS) &
66                  MXC_F_OWM_REVA_CFG_INT_PULLUP_ENABLE) |
67                 ((ext_pu_en << MXC_F_OWM_REVA_CFG_EXT_PULLUP_ENABLE_POS) &
68                  MXC_F_OWM_REVA_CFG_EXT_PULLUP_ENABLE) |
69                 ((cfg->long_line_mode << MXC_F_OWM_REVA_CFG_LONG_LINE_MODE_POS) &
70                  MXC_F_OWM_REVA_CFG_LONG_LINE_MODE));
71 
72     // If external pullup is enabled, set the mode
73     if (ext_pu_en) {
74         MXC_SETFIELD(owm->cfg, MXC_F_OWM_REVA_CFG_EXT_PULLUP_MODE,
75                      cfg->ext_pu_mode << MXC_F_OWM_REVA_CFG_EXT_PULLUP_MODE_POS);
76     }
77 
78     // Clear all interrupt flags
79     owm->intfl = owm->intfl;
80 
81     return E_NO_ERROR;
82 }
83 
84 /* ************************************************************************* */
MXC_OWM_RevA_Shutdown(mxc_owm_reva_regs_t * owm)85 void MXC_OWM_RevA_Shutdown(mxc_owm_reva_regs_t *owm)
86 {
87     // Disable and clear interrupts
88     owm->inten = 0;
89     owm->intfl = owm->intfl;
90 }
91 
92 /* ************************************************************************* */
MXC_OWM_RevA_Reset(mxc_owm_reva_regs_t * owm)93 int MXC_OWM_RevA_Reset(mxc_owm_reva_regs_t *owm)
94 {
95     owm->intfl = MXC_F_OWM_REVA_INTFL_OW_RESET_DONE; // Clear the reset flag
96     owm->ctrl_stat |= MXC_F_OWM_REVA_CTRL_STAT_START_OW_RESET; // Generate a reset pulse
97 
98     while ((owm->intfl & MXC_F_OWM_REVA_INTFL_OW_RESET_DONE) == 0) {}
99     // Wait for reset time slot to complete
100 
101     return MXC_OWM_GetPresenceDetect(); // Return presence pulse detect status
102 }
103 
104 /* ************************************************************************* */
MXC_OWM_RevA_TouchByte(mxc_owm_reva_regs_t * owm,uint8_t data)105 int MXC_OWM_RevA_TouchByte(mxc_owm_reva_regs_t *owm, uint8_t data)
106 {
107     owm->cfg &= ~MXC_F_OWM_REVA_CFG_SINGLE_BIT_MODE; // Set to 8 bit mode
108     owm->intfl = (MXC_F_OWM_REVA_INTFL_TX_DATA_EMPTY | MXC_F_OWM_REVA_INTEN_LINE_SHORT |
109                   MXC_F_OWM_REVA_INTFL_RX_DATA_READY); // Clear the flags
110     owm->data = (data << MXC_F_OWM_REVA_DATA_TX_RX_POS) & MXC_F_OWM_REVA_DATA_TX_RX; // Write data
111 
112     while ((owm->intfl & MXC_F_OWM_REVA_INTFL_TX_DATA_EMPTY) == 0) {}
113     // Wait for data to be sent
114 
115     while ((owm->intfl & MXC_F_OWM_REVA_INTFL_RX_DATA_READY) == 0) {}
116     // Wait for data to be read
117 
118     // Check error flag
119     if (owm->intfl & MXC_F_OWM_REVA_INTEN_LINE_SHORT) {
120         return E_COMM_ERR; // Wire was low before transaction
121     }
122 
123     return (owm->data >> MXC_F_OWM_REVA_DATA_TX_RX_POS) & 0xFF; // Return the data read
124 }
125 
126 /* ************************************************************************* */
MXC_OWM_RevA_WriteByte(uint8_t data)127 int MXC_OWM_RevA_WriteByte(uint8_t data)
128 {
129     // Send one byte of data and verify the data sent = data parameter
130     return (MXC_OWM_TouchByte(data) == data) ? E_NO_ERROR : E_COMM_ERR;
131 }
132 
133 /* ************************************************************************* */
MXC_OWM_RevA_ReadByte(void)134 int MXC_OWM_RevA_ReadByte(void)
135 {
136     // Read one byte of data
137     return MXC_OWM_TouchByte(0xFF);
138 }
139 
140 /* ************************************************************************* */
MXC_OWM_RevA_TouchBit(mxc_owm_reva_regs_t * owm,uint8_t bit)141 int MXC_OWM_RevA_TouchBit(mxc_owm_reva_regs_t *owm, uint8_t bit)
142 {
143     owm->cfg |= MXC_F_OWM_REVA_CFG_SINGLE_BIT_MODE; // Set to 1 bit mode
144     owm->intfl = (MXC_F_OWM_REVA_INTFL_TX_DATA_EMPTY | MXC_F_OWM_REVA_INTEN_LINE_SHORT |
145                   MXC_F_OWM_REVA_INTFL_RX_DATA_READY); // Clear the flags
146     owm->data = (bit << MXC_F_OWM_REVA_DATA_TX_RX_POS) & MXC_F_OWM_REVA_DATA_TX_RX; // Write data
147 
148     while ((owm->intfl & MXC_F_OWM_REVA_INTFL_TX_DATA_EMPTY) == 0) {}
149     // Wait for data to be sent
150 
151     while ((owm->intfl & MXC_F_OWM_REVA_INTFL_RX_DATA_READY) == 0) {}
152     // Wait for data to be read
153 
154     // Check error flag
155     if (owm->intfl & MXC_F_OWM_REVA_INTEN_LINE_SHORT) {
156         return E_COMM_ERR; // Wire was low before transaction
157     }
158 
159     return (owm->data >> MXC_F_OWM_REVA_DATA_TX_RX_POS) & 0x1; // Return the bit read
160 }
161 
162 /* ************************************************************************* */
MXC_OWM_RevA_WriteBit(uint8_t bit)163 int MXC_OWM_RevA_WriteBit(uint8_t bit)
164 {
165     // Send a bit and verify the bit sent = bit parameter
166     return (MXC_OWM_TouchBit(bit) == bit) ? E_NO_ERROR : E_COMM_ERR;
167 }
168 
169 /* ************************************************************************* */
MXC_OWM_RevA_ReadBit(void)170 int MXC_OWM_RevA_ReadBit(void)
171 {
172     // Read a bit
173     return MXC_OWM_TouchBit(1);
174 }
175 
176 /* ************************************************************************* */
MXC_OWM_RevA_Write(mxc_owm_reva_regs_t * owm,uint8_t * data,int len)177 int MXC_OWM_RevA_Write(mxc_owm_reva_regs_t *owm, uint8_t *data, int len)
178 {
179     int num = 0;
180 
181     owm->cfg &= ~MXC_F_OWM_REVA_CFG_SINGLE_BIT_MODE; // Set to 8 bit mode
182 
183     while (num < len) { // Loop for number of bytes to write
184         if (MXC_OWM_WriteByte(data[num]) != E_NO_ERROR) {
185             return E_COMM_ERR;
186         }
187 
188         num++; // Keep track of how many bytes written
189     }
190 
191     return num; // Return number of bytes written
192 }
193 
194 /* ************************************************************************* */
MXC_OWM_RevA_Read(mxc_owm_reva_regs_t * owm,uint8_t * data,int len)195 int MXC_OWM_RevA_Read(mxc_owm_reva_regs_t *owm, uint8_t *data, int len)
196 {
197     int num = 0;
198 
199     owm->cfg &= ~MXC_F_OWM_REVA_CFG_SINGLE_BIT_MODE; // Set to 8 bit mode
200 
201     while (num < len) { // Loop for number of bytes to read
202         // Store read data into buffer
203         data[num] = MXC_OWM_ReadByte();
204 
205         num++; // Keep track of how many bytes read
206     }
207 
208     return num; // Return number of bytes read
209 }
210 
211 /* ************************************************************************* */
MXC_OWM_RevA_ReadROM(uint8_t * ROMCode)212 int MXC_OWM_RevA_ReadROM(uint8_t *ROMCode)
213 {
214     int num_read;
215 
216     // Send reset and wait for presence pulse
217     if (MXC_OWM_Reset()) {
218         // Send Read ROM command code
219         if (MXC_OWM_WriteByte(READ_ROM_COMMAND) == E_NO_ERROR) {
220             // Read 8 bytes and store in buffer
221             num_read = MXC_OWM_Read(ROMCode, 8);
222 
223             // Check the number of bytes read
224             if (num_read != 8) {
225                 return E_COMM_ERR;
226             }
227         } else {
228             // Write failed
229             return E_COMM_ERR;
230         }
231     } else {
232         // No presence pulse
233         return E_COMM_ERR;
234     }
235 
236     return E_NO_ERROR;
237 }
238 
239 /* ************************************************************************* */
MXC_OWM_RevA_MatchROM(uint8_t * ROMCode)240 int MXC_OWM_RevA_MatchROM(uint8_t *ROMCode)
241 {
242     int num_wrote;
243 
244     // Send reset and wait for presence pulse
245     if (MXC_OWM_Reset()) {
246         // Send match ROM command code
247         if (MXC_OWM_WriteByte(MATCH_ROM_COMMAND) == E_NO_ERROR) {
248             // Write 8 bytes in ROMCode buffer
249             num_wrote = MXC_OWM_Write(ROMCode, 8);
250 
251             // Check the number of bytes written
252             if (num_wrote != 8) {
253                 return E_COMM_ERR;
254             }
255         } else {
256             // Write failed
257             return E_COMM_ERR;
258         }
259     } else {
260         // No presence pulse
261         return E_COMM_ERR;
262     }
263 
264     return E_NO_ERROR;
265 }
266 
267 /* ************************************************************************* */
MXC_OWM_RevA_ODMatchROM(mxc_owm_reva_regs_t * owm,uint8_t * ROMCode)268 int MXC_OWM_RevA_ODMatchROM(mxc_owm_reva_regs_t *owm, uint8_t *ROMCode)
269 {
270     int num_wrote;
271 
272     // Set to standard speed
273     owm->cfg &= ~(MXC_F_OWM_REVA_CFG_OVERDRIVE);
274 
275     // Send reset and wait for presence pulse
276     if (MXC_OWM_Reset()) {
277         // Send Overdrive match ROM command code
278         if (MXC_OWM_WriteByte(OD_MATCH_ROM_COMMAND) == E_NO_ERROR) {
279             // Set overdrive
280             owm->cfg |= MXC_F_OWM_REVA_CFG_OVERDRIVE;
281 
282             // Write 8 bytes in ROMCode buffer
283             num_wrote = MXC_OWM_Write(ROMCode, 8);
284 
285             // Check the number of bytes written
286             if (num_wrote != 8) {
287                 return E_COMM_ERR;
288             }
289         } else {
290             // Write failed
291             return E_COMM_ERR;
292         }
293     } else {
294         // No presence pulse
295         return E_COMM_ERR;
296     }
297 
298     return E_NO_ERROR;
299 }
300 
301 /* ************************************************************************* */
MXC_OWM_RevA_SkipROM(void)302 int MXC_OWM_RevA_SkipROM(void)
303 {
304     // Send reset and wait for presence pulse
305     if (MXC_OWM_Reset()) {
306         // Send skip ROM command code
307         return MXC_OWM_WriteByte(SKIP_ROM_COMMAND);
308     } else {
309         // No presence pulse
310         return E_COMM_ERR;
311     }
312 }
313 
314 /* ************************************************************************* */
MXC_OWM_RevA_ODSkipROM(mxc_owm_reva_regs_t * owm)315 int MXC_OWM_RevA_ODSkipROM(mxc_owm_reva_regs_t *owm)
316 {
317     // Set to standard speed
318     owm->cfg &= ~(MXC_F_OWM_REVA_CFG_OVERDRIVE);
319 
320     // Send reset and wait for presence pulse
321     if (MXC_OWM_Reset()) {
322         // Send Overdrive skip ROM command code
323         if (MXC_OWM_WriteByte(OD_SKIP_ROM_COMMAND) == E_NO_ERROR) {
324             // Set overdrive speed
325             owm->cfg |= MXC_F_OWM_REVA_CFG_OVERDRIVE;
326 
327             return E_NO_ERROR;
328         } else {
329             // Write failed
330             return E_COMM_ERR;
331         }
332     } else {
333         // No presence pulse
334         return E_COMM_ERR;
335     }
336 }
337 
338 /* ************************************************************************* */
MXC_OWM_RevA_Resume(void)339 int MXC_OWM_RevA_Resume(void)
340 {
341     // Send reset and wait for presence pulse
342     if (MXC_OWM_Reset()) {
343         // Send resume command code
344         return MXC_OWM_WriteByte(RESUME_COMMAND);
345     } else {
346         // No presence pulse
347         return E_COMM_ERR;
348     }
349 }
350 
351 /* ************************************************************************* */
MXC_OWM_RevA_SearchROM(mxc_owm_reva_regs_t * owm,int newSearch,uint8_t * ROMCode)352 int MXC_OWM_RevA_SearchROM(mxc_owm_reva_regs_t *owm, int newSearch, uint8_t *ROMCode)
353 {
354     int nibble_start_bit = 1;
355     int rom_byte_number = 0;
356     uint8_t rom_nibble_mask = 0x0F;
357     uint8_t search_direction;
358     int readValue;
359     int sentBits;
360     int discrepancy;
361     int bit_position;
362     int discrepancy_mask;
363     int last_zero = 0;
364     uint8_t crc8;
365     int search_result = 0;
366 
367     // Clear ROM array
368     memset(ROMCode, 0x0, 8);
369 
370     if (newSearch) {
371         // Reset all global variables to start search from beginning
372         LastDiscrepancy = 0;
373         LastDeviceFlag = 0;
374     }
375 
376     // Check if the last call was the last device
377     if (LastDeviceFlag) {
378         // Reset the search
379         LastDiscrepancy = 0;
380         LastDeviceFlag = 0;
381         return search_result;
382     }
383 
384     // Send reset and wait for presence pulse
385     if (MXC_OWM_Reset()) {
386         // Send the search command
387         MXC_OWM_WriteByte(SEARCH_ROM_COMMAND);
388 
389         // Set search ROM accelerator bit
390         owm->ctrl_stat |= MXC_F_OWM_REVA_CTRL_STAT_SRA_MODE;
391 
392         // Loop through all ROM bytes 0-7(this loops 2 times per byte)
393         while (rom_byte_number < 8) {
394             // Each loop finds the discrepancy bits and finds 4 bits(nibble) of the ROM
395 
396             // Set the search direction the same as last time for the nibble masked
397             search_direction = ROMCode[rom_byte_number] & rom_nibble_mask;
398 
399             // If the upper nibble is the mask then shift bits to lower nibble
400             if (rom_nibble_mask > 0x0F) {
401                 search_direction = search_direction >> 4;
402             }
403 
404             // Get the last discrepancy bit position relative to the nibble start bit
405             bit_position = LastDiscrepancy - nibble_start_bit;
406 
407             // Check if last discrepancy is within this nibble
408             if ((bit_position >= 0) && (bit_position < 4)) {
409                 // Last discrepancy is within this nibble
410                 // Set the bit of the last discrepancy bit
411                 search_direction |= (1 << (bit_position));
412             }
413 
414             // Performs two read bits and a write bit for 4 bits of the ROM
415             readValue = MXC_OWM_TouchByte(search_direction);
416             // Get discrepancy flags
417             discrepancy = readValue & 0xF;
418             // Get the 4 bits sent to select the ROM
419             sentBits = (readValue >> 4) & 0xF;
420 
421             // Store the bit location of the MSB discrepancy with sentbit = 0
422             if (discrepancy) {
423                 // Initialize bit_position to MSB of nibble
424                 bit_position = 3;
425 
426                 while (bit_position >= 0) {
427                     // Get discrepancy flag of the current bit position
428                     discrepancy_mask = discrepancy & (1 << bit_position);
429 
430                     // If there is a discrepancy and the sent bit is 0 save this bit position
431                     if ((discrepancy_mask) && !(sentBits & discrepancy_mask)) {
432                         last_zero = nibble_start_bit + bit_position;
433                         break;
434                     }
435 
436                     bit_position--;
437                 }
438             }
439 
440             // Clear the nibble
441             ROMCode[rom_byte_number] &= ~rom_nibble_mask;
442 
443             // Store the sentBits in the ROMCode
444             if (rom_nibble_mask > 0x0F) {
445                 ROMCode[rom_byte_number] |= (sentBits << 4);
446             } else {
447                 ROMCode[rom_byte_number] |= sentBits;
448             }
449 
450             // Increment the nibble start bit and shift mask
451             nibble_start_bit += 4;
452             rom_nibble_mask <<= 4;
453 
454             // If the mask is 0 then go to new ROM byte rom_byte_number and reset mask
455             if (rom_nibble_mask == 0) {
456                 rom_byte_number++;
457                 rom_nibble_mask = 0x0F;
458             }
459         } // End while(rom_byte_number < 8)
460 
461         // Clear search ROM accelerator
462         owm->ctrl_stat &= ~(MXC_F_OWM_REVA_CTRL_STAT_SRA_MODE);
463 
464         // Calculate CRC to verify ROM code is correct
465         crc8 = CalculateCRC8(ROMCode, 7);
466 
467         // If the search was successful then
468         if ((nibble_start_bit >= 65) && (crc8 == ROMCode[7])) {
469             // Search successful so set LastDiscrepancy,LastDeviceFlag,search_result
470             LastDiscrepancy = last_zero;
471 
472             // Check for last device
473             if (LastDiscrepancy == 0) {
474                 LastDeviceFlag = 1;
475             }
476 
477             search_result = 1;
478         }
479     } // End if(MXC_OWM_Reset)
480 
481     // If no device found then reset counters so next 'search' will be like a first
482     if (!search_result || !ROMCode[0]) {
483         LastDiscrepancy = 0;
484         LastDeviceFlag = 0;
485         search_result = 0;
486     }
487 
488     return search_result;
489 }
490 
491 /* ************************************************************************* */
MXC_OWM_RevA_ClearFlags(mxc_owm_reva_regs_t * owm,uint32_t mask)492 void MXC_OWM_RevA_ClearFlags(mxc_owm_reva_regs_t *owm, uint32_t mask)
493 {
494     owm->intfl = mask;
495 }
496 
497 /* ************************************************************************* */
MXC_OWM_RevA_GetFlags(mxc_owm_reva_regs_t * owm)498 unsigned MXC_OWM_RevA_GetFlags(mxc_owm_reva_regs_t *owm)
499 {
500     return (owm->intfl);
501 }
502 
503 /* ************************************************************************* */
MXC_OWM_RevA_SetExtPullup(mxc_owm_reva_regs_t * owm,int enable)504 void MXC_OWM_RevA_SetExtPullup(mxc_owm_reva_regs_t *owm, int enable)
505 {
506     if (enable) {
507         owm->cfg |= MXC_F_OWM_REVA_CFG_EXT_PULLUP_ENABLE;
508     } else {
509         owm->cfg &= ~(MXC_F_OWM_REVA_CFG_EXT_PULLUP_ENABLE);
510     }
511 }
512 
513 /* ************************************************************************* */
MXC_OWM_RevA_SetOverdrive(mxc_owm_reva_regs_t * owm,int enable)514 void MXC_OWM_RevA_SetOverdrive(mxc_owm_reva_regs_t *owm, int enable)
515 {
516     if (enable) {
517         owm->cfg |= MXC_F_OWM_REVA_CFG_OVERDRIVE;
518     } else {
519         owm->cfg &= ~(MXC_F_OWM_REVA_CFG_OVERDRIVE);
520     }
521 }
522 
523 /* ************************************************************************* */
MXC_OWM_RevA_EnableInt(mxc_owm_reva_regs_t * owm,int flags)524 void MXC_OWM_RevA_EnableInt(mxc_owm_reva_regs_t *owm, int flags)
525 {
526     owm->inten |= flags;
527 }
528 
529 /* ************************************************************************* */
MXC_OWM_RevA_DisableInt(mxc_owm_reva_regs_t * owm,int flags)530 void MXC_OWM_RevA_DisableInt(mxc_owm_reva_regs_t *owm, int flags)
531 {
532     owm->inten &= ~flags;
533 }
534 
535 /* ************************************************************************* */
MXC_OWM_RevA_SetForcePresenceDetect(mxc_owm_reva_regs_t * owm,int enable)536 int MXC_OWM_RevA_SetForcePresenceDetect(mxc_owm_reva_regs_t *owm, int enable)
537 {
538     MXC_SETFIELD(owm->cfg, MXC_F_OWM_REVA_CFG_FORCE_PRES_DET,
539                  enable << MXC_F_OWM_REVA_CFG_FORCE_PRES_DET_POS);
540     return E_NO_ERROR;
541 }
542 
543 /* ************************************************************************* */
MXC_OWM_RevA_SetInternalPullup(mxc_owm_reva_regs_t * owm,int enable)544 int MXC_OWM_RevA_SetInternalPullup(mxc_owm_reva_regs_t *owm, int enable)
545 {
546     MXC_SETFIELD(owm->cfg, MXC_F_OWM_REVA_CFG_INT_PULLUP_ENABLE,
547                  enable << MXC_F_OWM_REVA_CFG_INT_PULLUP_ENABLE_POS);
548     return E_NO_ERROR;
549 }
550 
551 /* ************************************************************************* */
MXC_OWM_RevA_SetExternalPullup(mxc_owm_reva_regs_t * owm,mxc_owm_ext_pu_t ext_pu_mode)552 int MXC_OWM_RevA_SetExternalPullup(mxc_owm_reva_regs_t *owm, mxc_owm_ext_pu_t ext_pu_mode)
553 {
554     switch (ext_pu_mode) {
555     case MXC_OWM_EXT_PU_ACT_HIGH:
556         owm->cfg |= MXC_F_OWM_REVA_CFG_EXT_PULLUP_ENABLE;
557         owm->cfg &= ~MXC_F_OWM_REVA_CFG_EXT_PULLUP_MODE;
558         break;
559 
560     case MXC_OWM_EXT_PU_ACT_LOW:
561         owm->cfg &= ~MXC_F_OWM_REVA_CFG_EXT_PULLUP_ENABLE;
562         owm->cfg &= ~MXC_F_OWM_REVA_CFG_EXT_PULLUP_MODE;
563         break;
564 
565     case MXC_OWM_EXT_PU_UNUSED:
566         owm->cfg &= ~MXC_F_OWM_REVA_CFG_EXT_PULLUP_ENABLE;
567         owm->cfg |= MXC_F_OWM_REVA_CFG_EXT_PULLUP_MODE;
568         break;
569     }
570 
571     return E_NO_ERROR;
572 }
573 
574 /* ************************************************************************* */
MXC_OWM_RevA_SystemClockUpdated(mxc_owm_reva_regs_t * owm)575 int MXC_OWM_RevA_SystemClockUpdated(mxc_owm_reva_regs_t *owm)
576 {
577     uint32_t mxc_owm_clk, clk_div = 0;
578 
579     // Configure clk divisor to get 1MHz OWM clk
580     mxc_owm_clk = PeripheralClock;
581 
582     if (mxc_owm_clk == 0) {
583         return E_UNINITIALIZED;
584     }
585 
586     // Return error if clk doesn't divide evenly to 1MHz
587     if (mxc_owm_clk % MXC_OWM_CLK_FREQ) {
588         return E_NOT_SUPPORTED;
589     }
590 
591     clk_div = (mxc_owm_clk / (MXC_OWM_CLK_FREQ));
592 
593     // Can not support lower frequencies
594     if (clk_div == 0) {
595         return E_NOT_SUPPORTED;
596     }
597 
598     // Set clk divisor
599     owm->clk_div_1us = (clk_div << MXC_F_OWM_REVA_CLK_DIV_1US_DIVISOR_POS) &
600                        MXC_F_OWM_REVA_CLK_DIV_1US_DIVISOR;
601 
602     return E_NO_ERROR;
603 }
604 
605 /* ************************************************************************ */
MXC_OWM_RevA_SetSearchROMAccelerator(mxc_owm_reva_regs_t * owm,int enable)606 int MXC_OWM_RevA_SetSearchROMAccelerator(mxc_owm_reva_regs_t *owm, int enable)
607 {
608     MXC_SETFIELD(owm->ctrl_stat, MXC_F_OWM_REVA_CTRL_STAT_SRA_MODE,
609                  enable << MXC_F_OWM_REVA_CTRL_STAT_SRA_MODE_POS);
610     return E_NO_ERROR;
611 }
612 
613 /* ************************************************************************* */
MXC_OWM_RevA_BitBang_Init(mxc_owm_reva_regs_t * owm,int initialState)614 int MXC_OWM_RevA_BitBang_Init(mxc_owm_reva_regs_t *owm, int initialState)
615 {
616     owm->cfg |= MXC_F_OWM_REVA_CFG_BIT_BANG_EN;
617 
618     MXC_SETFIELD(owm->ctrl_stat, MXC_F_OWM_REVA_CTRL_STAT_BIT_BANG_OE,
619                  initialState << MXC_F_OWM_REVA_CTRL_STAT_BIT_BANG_OE_POS);
620 
621     return E_NO_ERROR;
622 }
623 
624 /* ************************************************************************* */
MXC_OWM_RevA_BitBang_Read(mxc_owm_reva_regs_t * owm)625 int MXC_OWM_RevA_BitBang_Read(mxc_owm_reva_regs_t *owm)
626 {
627     return !!(owm->ctrl_stat & MXC_F_OWM_REVA_CTRL_STAT_BIT_BANG_OE);
628 }
629 
630 /* ************************************************************************* */
MXC_OWM_RevA_BitBang_Write(mxc_owm_reva_regs_t * owm,int state)631 int MXC_OWM_RevA_BitBang_Write(mxc_owm_reva_regs_t *owm, int state)
632 {
633     MXC_SETFIELD(owm->ctrl_stat, MXC_F_OWM_REVA_CTRL_STAT_BIT_BANG_OE,
634                  state << MXC_F_OWM_REVA_CTRL_STAT_BIT_BANG_OE_POS);
635     return E_NO_ERROR;
636 }
637 
638 /* ************************************************************************* */
MXC_OWM_RevA_BitBang_Disable(mxc_owm_reva_regs_t * owm)639 int MXC_OWM_RevA_BitBang_Disable(mxc_owm_reva_regs_t *owm)
640 {
641     owm->cfg &= ~MXC_F_OWM_REVA_CFG_BIT_BANG_EN;
642     return E_NO_ERROR;
643 }
644 
645 /* ************************************************************************* */
CalculateCRC8(uint8_t * data,int len)646 static uint8_t CalculateCRC8(uint8_t *data, int len)
647 {
648     int i;
649     uint8_t crc = 0;
650 
651     for (i = 0; i < len; i++) {
652         crc = update_crc8(crc, data[i]);
653     }
654 
655     return crc;
656 }
657 
658 /* ************************************************************************* */
update_crc8(uint8_t crc,uint8_t val)659 static uint8_t update_crc8(uint8_t crc, uint8_t val)
660 {
661     uint8_t inc, tmp;
662 
663     for (inc = 0; inc < 8; inc++) {
664         tmp = (uint8_t)(crc << 7); // Save X7 bit value
665         crc >>= 1; // Shift crc
666 
667         if (((tmp >> 7) ^ (val & 0x01)) == 1) { // If X7 xor X8(input data)
668             crc ^= 0x8c; // XOR crc with X4 and X5, X1 = X7^X8
669             crc |= 0x80; // Carry
670         }
671 
672         val >>= 1;
673     }
674 
675     return crc;
676 }
677