blob: 1e9ae0a4bb9b7063f552ba22c16d2577a4471307 [file] [log] [blame]
/*
* Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <utils/util.h>
#include <platsupport/io.h>
/*
* These macros are used to check if compat_list or init_func
* passed to PS_DRIVER_MODULE_DEFINE are not NULL or 0
*/
#define PS_INVALID_ADDR_0 0,
#define PS_INVALID_ADDR_NULL 0,
#define __third_arg(_, __, val, ...) val
#define IS_NULL(compat_list, init_func) \
__IS_NULL(PS_INVALID_##compat_list, PS_INVALID_##init_func)
// arg1 and arg2 will expand to real argument only when the pointers are NULL or 0
// thus selecting the thrid arg will tell us whether one of them is NULL
#define __IS_NULL(arg1, arg2) __third_arg(arg1 arg2 INVALID, INVALID, VALID)
#define PS_DRIVER_MODULE_DEFINE(name, compat_list, init_func) \
__PS_DRIVER_MODULE_DEFINE(IS_NULL(ADDR_##compat_list, ADDR_##init_func), \
name, compat_list, init_func)
#define __PS_DRIVER_MODULE_DEFINE(null, name, compat_list, init_func) \
____PS_DRIVER_MODULE_DEFINE(null, name, compat_list, init_func)
#define ____PS_DRIVER_MODULE_DEFINE(null, name, compat_list, init_func) \
PS_DRIVER_MODULE_DEFINE_##null(name, compat_list, init_func)
#define PS_DRIVER_MODULE_DEFINE_INVALID(name, compat_list, init_func) \
"compat_list and init_func must not be NULL"
#define PS_DRIVER_MODULE_DEFINE_VALID(name, compat_list, init_func) \
static ps_driver_module_t name = { \
.compatible_list = compat_list, \
.init = init_func \
}; \
USED SECTION("_driver_modules") ps_driver_module_t *name##_ptr = &name;
#define PS_DRIVER_INIT_SUCCESS 0
#define PS_DRIVER_INIT_DEFER 1
/*
* Returns:
* - negative on error
* - PS_DRIVER_INIT_SUCCESS on success
* - PS_DRIVER_INIT_DEFER when you want to defer this initialisation function until later
*/
typedef int (*ps_driver_init_fn_t)(ps_io_ops_t *io_ops, const char *device_path);
typedef struct {
const char **compatible_list;
ps_driver_init_fn_t init;
} ps_driver_module_t;