1 /*
2  * Copyright (c) 2019, The Linux Foundation. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *    * Redistributions of source code must retain the above copyright
8  *      notice, this list of conditions and the following disclaimer.
9  *    * Redistributions in binary form must reproduce the above
10  *      copyright notice, this list of conditions and the following
11  *      disclaimer in the documentation and/or other materials provided
12  *      with the distribution.
13  *    * Neither the name of The Linux Foundation nor the names of its
14  *      contributors may be used to endorse or promote products derived
15  *      from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 #define FARF_ERROR 1
30 #include "HAP_farf.h"
31 #include "platform_libs.h"
32 #include "AEEatomic.h"
33 #include "AEEstd.h"
34 #include "AEEStdErr.h"
35 #include <stdio.h>
36 #include <assert.h>
37 #include "verify.h"
38 
39 extern struct platform_lib* (*pl_list[])(void);
40 static uint32 atomic_IfNotThenAdd(uint32* volatile puDest, uint32 uCompare, int nAdd);
41 
pl_lib_init(struct platform_lib * (* plf)(void))42 int pl_lib_init(struct platform_lib* (*plf)(void)) {
43    int nErr = AEE_SUCCESS;
44    struct platform_lib* pl = plf();
45    if(1 == atomic_Add(&pl->uRefs, 1)) {
46       if(pl->init) {
47          FARF(HIGH, "calling init for %s",pl->name);
48          nErr = pl->init();
49          FARF(HIGH, "init for %s returned %x",pl->name, nErr);
50       }
51       pl->nErr = nErr;
52    }
53    if(pl->nErr != AEE_SUCCESS) {
54       VERIFY_EPRINTF("Error %x: %s init failed", nErr, pl->name);
55    }
56    return pl->nErr;
57 }
58 
pl_lib_deinit(struct platform_lib * (* plf)(void))59 void pl_lib_deinit(struct platform_lib* (*plf)(void)) {
60    struct platform_lib* pl = plf();
61    if(1 == atomic_IfNotThenAdd(&pl->uRefs, 0, -1)) {
62       if(pl->deinit && pl->nErr == 0) {
63          pl->deinit();
64       }
65    }
66    return;
67 }
68 
pl_init_lst(struct platform_lib * (* lst[])(void))69 static int pl_init_lst(struct platform_lib* (*lst[])(void)) {
70    int nErr = AEE_SUCCESS;
71    int ii;
72    for(ii = 0; lst[ii] != 0; ++ii) {
73       nErr = pl_lib_init(lst[ii]);
74       if(nErr != 0) {
75          break;
76       }
77    }
78    if(nErr != AEE_SUCCESS) {
79 	VERIFY_EPRINTF("Error %x: plinit failed\n", nErr);
80    }
81    return nErr;
82 
83 }
pl_init(void)84 int pl_init(void) {
85    int nErr = pl_init_lst(pl_list);
86    return nErr;
87 }
88 
pl_deinit_lst(struct platform_lib * (* lst[])(void))89 static void pl_deinit_lst(struct platform_lib* (*lst[])(void)) {
90    int size, ii;
91    for(size = 0; lst[size] != 0; ++size) {;}
92    for(ii = size - 1; ii >= 0; --ii) {
93       pl_lib_deinit(lst[ii]);
94    }
95    return;
96 }
97 
98 
pl_deinit(void)99 void pl_deinit(void) {
100    pl_deinit_lst(pl_list);
101    return;
102 }
103 
atomic_IfNotThenAdd(uint32 * volatile puDest,uint32 uCompare,int nAdd)104 static uint32 atomic_IfNotThenAdd(uint32* volatile puDest, uint32 uCompare, int nAdd)
105 {
106    uint32 uPrev;
107    uint32 uCurr;
108    do {
109       //check puDest
110       uCurr = *puDest;
111       uPrev = uCurr;
112       //see if we need to update it
113       if(uCurr != uCompare) {
114          //update it
115          uPrev = atomic_CompareAndExchange(puDest, uCurr + nAdd, uCurr);
116       }
117       //verify that the value was the same during the update as when we decided to update
118    } while(uCurr != uPrev);
119    return uPrev;
120 }
121 
122