blob: 4cd576b05ce599a5628aeeb5ea52796ef03c7857 [file] [log] [blame]
/*
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define FARF_ERROR 1
#include "HAP_farf.h"
#include "platform_libs.h"
#include "AEEatomic.h"
#include "AEEstd.h"
#include "AEEStdErr.h"
#include <stdio.h>
#include <assert.h>
#include "verify.h"
extern struct platform_lib* (*pl_list[])(void);
static uint32 atomic_IfNotThenAdd(uint32* volatile puDest, uint32 uCompare, int nAdd);
int pl_lib_init(struct platform_lib* (*plf)(void)) {
int nErr = AEE_SUCCESS;
struct platform_lib* pl = plf();
if(1 == atomic_Add(&pl->uRefs, 1)) {
if(pl->init) {
FARF(HIGH, "calling init for %s",pl->name);
nErr = pl->init();
FARF(HIGH, "init for %s returned %x",pl->name, nErr);
}
pl->nErr = nErr;
}
if(pl->nErr != AEE_SUCCESS) {
VERIFY_EPRINTF("Error %x: %s init failed", nErr, pl->name);
}
return pl->nErr;
}
void pl_lib_deinit(struct platform_lib* (*plf)(void)) {
struct platform_lib* pl = plf();
if(1 == atomic_IfNotThenAdd(&pl->uRefs, 0, -1)) {
if(pl->deinit && pl->nErr == 0) {
pl->deinit();
}
}
return;
}
static int pl_init_lst(struct platform_lib* (*lst[])(void)) {
int nErr = AEE_SUCCESS;
int ii;
for(ii = 0; lst[ii] != 0; ++ii) {
nErr = pl_lib_init(lst[ii]);
if(nErr != 0) {
break;
}
}
if(nErr != AEE_SUCCESS) {
VERIFY_EPRINTF("Error %x: plinit failed\n", nErr);
}
return nErr;
}
int pl_init(void) {
int nErr = pl_init_lst(pl_list);
return nErr;
}
static void pl_deinit_lst(struct platform_lib* (*lst[])(void)) {
int size, ii;
for(size = 0; lst[size] != 0; ++size) {;}
for(ii = size - 1; ii >= 0; --ii) {
pl_lib_deinit(lst[ii]);
}
return;
}
void pl_deinit(void) {
pl_deinit_lst(pl_list);
return;
}
static uint32 atomic_IfNotThenAdd(uint32* volatile puDest, uint32 uCompare, int nAdd)
{
uint32 uPrev;
uint32 uCurr;
do {
//check puDest
uCurr = *puDest;
uPrev = uCurr;
//see if we need to update it
if(uCurr != uCompare) {
//update it
uPrev = atomic_CompareAndExchange(puDest, uCurr + nAdd, uCurr);
}
//verify that the value was the same during the update as when we decided to update
} while(uCurr != uPrev);
return uPrev;
}