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