/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/*
 * Copyright (c) 2020 MediaTek Inc.
 */

#ifndef MHAL_DEMUX_COMMON_H
#define MHAL_DEMUX_COMMON_H

#include <linux/io.h>
#include <linux/bitops.h>
#include <linux/kern_levels.h>

#include "mhal_demux_regs.h"

//-------------------------------------------------------------------------------------------------
//  Debug Macro and Define
//-------------------------------------------------------------------------------------------------
#define MHAL_DEMUX_ERR(fmt, ...)                        pr_err(MHAL_LABLE fmt, ##__VA_ARGS__)
#define MHAL_DEMUX_WARN(fmt, ...)                       pr_warn(MHAL_LABLE fmt, ##__VA_ARGS__)
#define MHAL_DEMUX_INFO(fmt, ...)                       pr_info(MHAL_LABLE fmt, ##__VA_ARGS__)
#define MHAL_DEMUX_DEBUG(fmt, ...)                      pr_debug(MHAL_LABLE fmt, ##__VA_ARGS__)

#define MHAL_DEMUX_INVALID_PARAMETER                    (-2)
#define MHAL_DEMUX_FAIL                                 (-1)
#define MHAL_DEMUX_SUCCESS                              (0)

//-------------------------------------------------------------------------------------------------
//  Macro and Define
//-------------------------------------------------------------------------------------------------
#define TSIF_0					(0)
#define TSIF_FI					(1)
#define TSIF_1					(2)
#define TSIF_2					(3)
#define TLV_TSIF_0				(4)
#define TLV_TSIF_1				(5)
#define TLV_TSIF_2				(6)
#define TS_ALP_0				(7)
#define TS_ALP_FI				(8)

#define VFIFO_0					(0)
#define VFIFO_1					(1)

#define AFIFO_0					(0)
#define AFIFO_1					(1)
#define AFIFO_2					(2)
#define AFIFO_3					(3)

#define PVR_1					(0)
#define PVR_2					(1)
#define PVR_3					(2)
#define PVR_4					(3)

#define STC_0					(0)
#define STC_1					(1)
#define STC_2					(2)
#define STC_3					(3)

#define PCR_0					(0)
#define PCR_1					(1)

#define TSO_TSIF_1				(0)
#define TSO_TSIF_5				(1)
#define TSO_TSIF_6				(2)

#define NTP_0					(0)
#define NTP_1					(1)
#define NTP_2					(2)
#define NTP_3					(3)

#define MIU_BUS					(4)
#define FQ_PACKET_UNIT_LENGTH	(192)
#define VQ_PACKET_UNIT_LENGTH	(208)

#define MIU0_BUS_BASE			(0x20000000) // MIU0 Low 256MB
#define MIU1_BUS_BASE			(0xA0000000) // MIU1 Low 256MB

#define RIU_BANK_SIZE			(0x80)

#define PA_to_BA(pa)			(pa + MIU0_BUS_BASE)
#define BA_to_PA(ba)			(ba - MIU0_BUS_BASE)

#define HAS_BITS(val, bits)		((val) & (bits))
#define SET_BITS(val, bits)		((val) |= (bits))
#define CLEAR_BITS(val, bits)	((val) &= (~(bits)))

#define IS_TSIF_TS(path) ((path == TSIF_0) || (path == TSIF_FI) ||\
	(path == TSIF_1) || (path == TSIF_2))
#define IS_TSIF_TLV(path) ((path == TLV_TSIF_0) || (path == TLV_TSIF_1) ||\
	(path == TLV_TSIF_2))
#define IS_TSIF_ALP(path) ((path == TS_ALP_0) || (path == TS_ALP_FI))

#define REG16_MASK_SHIFT_WRITE(offset, mask, lshift, value) \
	reg16_mask_write(offset, mask, ((value) << (lshift)))
#define REG32_MASK_SHIFT_WRITE(offset, mask, lshift, value) \
	reg32_mask_write(offset, mask, ((value) << (lshift)))

#define REG32_SET_BIT(offset, nr) \
	reg32_set_mask(offset, (1 << nr))
#define REG32_CLEAR_BIT(offset, nr) \
	reg32_clear_mask(offset, (1 << nr))

#define MCU_CMD_RETRY_US		(80000)
#define MCU_CMD_RETRY_MAX		(80)
#define MCU_CMD_RETRY_MIN		(MCU_CMD_RETRY_MAX/2)
#define MCU_CMD_RETRY_TIMES		(MCU_CMD_RETRY_US/MCU_CMD_RETRY_MAX)

enum reg_base {
	REG_BASE_MIN = 0,

	REG_BASE_TSP_MIN = REG_BASE_MIN,
	REG_BASE_TSP_0 = REG_BASE_TSP_MIN,
	REG_BASE_TSP_1,
	REG_BASE_TSP_2,
	REG_BASE_TSP_3,
	REG_BASE_TSP_4,
	REG_BASE_TSP_5,
	REG_BASE_TSP_6,
	REG_BASE_TSP_7,
	REG_BASE_TSP_MAX,

	REG_BASE_TSO_MIN = 0x10,
	REG_BASE_TSO_0 = REG_BASE_TSO_MIN,
	REG_BASE_TSO_1,
	REG_BASE_TSO_2,
	REG_BASE_TSO_MAX,

	REG_BASE_TLV_MIN = 0x20,
	REG_BASE_TLV_0 = REG_BASE_TLV_MIN,
	REG_BASE_TLV_1,
	REG_BASE_TLV_MAX,

	REG_BASE_PAS_MIN = 0x30,
	REG_BASE_PAS_0 = REG_BASE_PAS_MIN,
	REG_BASE_PAS_1,
	REG_BASE_PAS_MAX,

	REG_BASE_CLKGEN_MIN = 0x40,
	REG_BASE_CLKGEN_0 = REG_BASE_CLKGEN_MIN,
	REG_BASE_CLKGEN_MAX,

	REG_BASE_TS_SAMPLE_MIN = 0x50,
	REG_BASE_TS_SAMPLE_0 = REG_BASE_TS_SAMPLE_MIN,
	REG_BASE_TS_SAMPLE_MAX,

	REG_BASE_CILINK_MIN = 0x60,
	REG_BASE_CILINK_0 = REG_BASE_CILINK_MIN,
	REG_BASE_CILINK_MAX,

	REG_BASE_ALP_MIN = 0x70,
	REG_BASE_ALP_0 = REG_BASE_ALP_MIN,
	REG_BASE_ALP_1,
	REG_BASE_ALP_MAX,

	REG_BASE_MAX = REG_BASE_ALP_MAX,
};

struct reg {
	enum reg_base base;
	u32 offset;
	u32 fld;
};

void mhal_demux_common_init(mtk_demux_riu_banks *riu_banks);
void mhal_demux_common_exit(void);
bool send_mcu_cmd(u32 cmd, u32 *pmsg0, u32 *pmsg1);
void indirect_write(u32 OR_addr, u32 value);
u32	 indirect_read(u32 OR_addr);
void reg32_write(REG16 __iomem *offset, u32 value);
u32	 reg32_read(REG16 __iomem *offset);
void reg32_set_mask(REG16 __iomem *offset, u32 mask);
void reg32_clear_mask(REG16 __iomem *offset, u32 mask);
void reg32_mask_write(REG16 __iomem *offset, u32 mask, u32 value);
u16 reg32_mask_read(REG16 __iomem *offset, u32 mask, u32 shift);
void reg16_write(REG16 __iomem *offset, u16 value);
u16	 reg16_read(REG16 __iomem *offset);
void reg16_set_bit(REG16 __iomem *offset, u8 nr);
void reg16_clear_bit(REG16 __iomem *offset, u8 nr);
bool reg16_test_bit(REG16 __iomem *offset, u8 nr);
void reg16_set_mask(REG16 __iomem *offset, u16 mask);
void reg16_clear_mask(REG16 __iomem *offset, u16 mask);
void reg16_mask_write(REG16 __iomem *offset, u16 mask, u16 value);
u16	 reg16_mask_read(REG16 __iomem *offset, u16 mask, u16 shift);

int reg_base_get(enum reg_base reg_base, REG16 __iomem **base);

#endif /* MHAL_DEMUX_COMMON_H */
