/******************************************************************************
* Copyright (C) 2024 Advanced Micro Devices, Inc. All Rights Reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/


#ifndef XPM_DEVICE_H_
#define XPM_DEVICE_H_

#include "xpm_node.h"
#include "xpm_power.h"
#include "xpm_clock.h"
#include "xpm_reset.h"

#ifdef __cplusplus
extern "C" {
#endif
#define DEFINE_DEV_STATES(S)	.States = (S), \
				.StatesCnt = ARRAY_SIZE(S)

#define DEFINE_DEV_TRANS(T)	.Trans = (T), \
				.TransCnt = ARRAY_SIZE(T)

#define DEVICE_NO_IDLE_REQ	(0U)
#define DEVICE_IDLE_REQ		(1U)
/* TODO: FIXME: this should be long to xpm_node.h which is autogenerated. */
#define XPM_NODESUBCL_DEV_MEM_CTRLR	5

#define DDRMC_DEVID(IDX)	NODEID((u32)XPM_NODECLASS_DEVICE, \
				       (u32)XPM_NODESUBCL_DEV_MEM_CTRLR, \
				       (u32)XPM_NODETYPE_DEV_DDR, (IDX))

typedef struct XPm_DeviceNode XPm_Device;

/* Device states */
typedef enum {
	XPM_DEVSTATE_UNUSED,
	XPM_DEVSTATE_RUNNING,
	XPM_DEVSTATE_PWR_ON,	/* Power up the island/domain */
	XPM_DEVSTATE_CLK_ON,	/* Enable clock */
	XPM_DEVSTATE_RST_OFF,	/* De-assert reset */
	XPM_DEVSTATE_RST_ON,	/* Assert reset */
	XPM_DEVSTATE_CLK_OFF,	/* Disable clock */
	XPM_DEVSTATE_PWR_OFF,	/* Power down */
	XPM_DEVSTATE_SUSPENDING,
	XPM_DEVSTATE_RUNTIME_SUSPEND,
	XPM_DEVSTATE_INITIALIZING,
	XPM_DEVSTATE_PENDING_PWR_DWN,
	XPM_DEVSTATE_HALT,
} XPm_DeviceState;

/* Device events */
typedef enum {
	XPM_DEVEVENT_BRINGUP_ALL,
	XPM_DEVEVENT_BRINGUP_CLKRST,
	XPM_DEVEVENT_SHUTDOWN,
	XPM_DEVEVENT_TIMER,
	XPM_DEVEVENT_RUNTIME_SUSPEND,
} XPm_DeviceEvent;

typedef struct XPm_DeviceAttr XPm_DeviceAttr;
typedef struct XPmRuntime_DeviceOps XPmRuntime_DeviceOps;

/**
 * The device class.  This is the base class for all the processor core,
 * memory bank and peripheral classes.
 */
struct XPm_DeviceNode {
	XPm_Node Node; /**< Node: Base class */
	u8 WfPwrUseCnt; /**< Pending power use count */
	XPm_Power *Power; /**< Device power node */
	XPm_ClockHandle *ClkHandles; /**< Head of the list of device clocks */
	XPm_ResetHandle *RstHandles; /**< Head of the list device resets */
	XPm_DeviceAttr *DevAttr;  /**< Device attributes */
};

struct XPm_RegAttr {
	u32 Offset:16;
	u32 Mask:16;
};

/* Device attributes for security, coherency and virtualization */
struct XPm_DeviceAttr {
	u32 SecurityBaseAddr;
	struct XPm_RegAttr Security[2];
	u32 CohVirtBaseAddr;
	struct XPm_RegAttr Coherency;
	struct XPm_RegAttr Virtualization;
};

/************************** Function Prototypes ******************************/
u32 XPmDevice_GetMemRegnCount(void);

XStatus XPmDevice_Init(XPm_Device *Device,
		u32 Id,
		u32 BaseAddress,
		XPm_Power *Power, XPm_ClockNode *Clock, XPm_ResetNode *Reset);

XStatus XPmDevice_AddClock(XPm_Device *Device, XPm_ClockNode *Clock);

XStatus XPmDevice_AddReset(XPm_Device *Device, XPm_ResetNode *Reset);

XStatus XPmDevice_Reset(const XPm_Device *Device, const XPm_ResetActions Action);


XPm_Device *XPmDevice_GetById(const u32 DeviceId);
XPm_Device *XPmDevice_GetByIndex(const u32 DeviceIndex);

XStatus XPmDevice_Release(const u32 SubsystemId, const u32 DeviceId,
			  const u32 CmdType);


XStatus XPmDevice_GetState(const u32 DeviceId, u32 *const DeviceState);

XStatus XPmDevice_AddParent(u32 Id, const u32 *Parents, u32 NumParents);

XStatus XPmDevice_BringUp(XPm_Device *Device);
XStatus XPmVirtDev_DeviceInit(XPm_Device *Device, u32 Id, XPm_Power *Power);
XPm_Device *XPmDevice_GetPlDeviceByIndex(const u32 DeviceIndex);
XStatus XPm_SetSysmonNode(u32 Id, u32 BaseAddress);
u32 XPm_GetSysmonByIndex(const u32 SysmonIndex);
XStatus XPmDevice_SdResetWorkaround(const XPm_Device *Device);
XPm_Device *XPmDevice_GetHbMonDeviceByIndex(const u32 DeviceIndex);
XStatus XPmDevice_IsClockActive(const XPm_Device *Device);


#ifdef __cplusplus
}
#endif

/** @} */
#endif /* XPM_DEVICE_H_ */
