/******************************************************************************
 * Hardware Programming Interface (HPI) for AudioScience ASI67xx series adapters
 * Constants and structures shared between host and SoC
 *
 * These PCIe bus adapters use a TMS320DM8147 ARM+DSP SoC
 * with PCIe bus mastering capability
 *
 * Copyright (C) 1997-2017  AudioScience Inc. <support@audioscience.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 ******************************************************************************/

#define FW6700_INFO_MAGIC_V0			(0x3591c7a5)
#define FW6700_DSP_INFO_MAGIC_V0		(0x6adeb8b1)
#define FW6700_BUS_MASTER_INTERFACE_MAGIC_V1	(0xd5edb625)

enum fw6700_state_v0 {
   FW6700_S_INVALID = 0,
   FW6700_S_EPERROR = 1,
   FW6700_S_EPREADY = 2,
   FW6700_S_HOSTREADY = 3,
   FW6700_S_EPDONE = 4,
   FW6700_S_HOSTDONE = 5,
   FW6700_S_EPSTARTINGDSP = 6,
   FW6700_S_EPHALTED = 7,
   FW6700_S_EPIDLE = 8,
   FW6700_S_HOSTPROTORESTART = 9,
   FW6700_S_EPPCIERESET = 10
};

static const char * const fw6700_state_names[] = {
   "FW6700_S_INVALID",
   "FW6700_S_EPERROR",
   "FW6700_S_EPREADY",
   "FW6700_S_HOSTREADY",
   "FW6700_S_EPDONE",
   "FW6700_S_HOSTDONE",
   "FW6700_S_EPSTARTINGDSP",
   "FW6700_S_EPHALTED",
   "FW6700_S_EPIDLE",
   "FW6700_S_HOSTPROTORESTART",
   "FW6700_S_EPPCIERESET"
};

static inline const char * fw6700_state_str(enum fw6700_state_v0 state)
{
	if ((state > 0) && (state < ARRAY_SIZE(fw6700_state_names)))
		return fw6700_state_names[state];
	else
		return fw6700_state_names[0];
};

struct fw6700_info_v0 {
   uint32_t magic;

   /* this struct's size */
   uint32_t size;

   /* this struct's version: high 16bits major ver, low 16bits minor ver */
   uint32_t version;

   /* Address of NULL terminated bootloader's version string */
   uint32_t bl_verstr_addr;

   uint32_t model;
   uint32_t hw_rev1;
   uint32_t hw_rev2;

   uint32_t error_code;

   uint32_t state;
   uint32_t pcie64bit;
   uint32_t haltarm;

   uint32_t soc_phymem_start_addr;
   uint32_t soc_phymem_size;

   uint32_t drvinfo_size;
   uint32_t drvinfo_addr;

   uint32_t entrypoint_addr;
};

/* ----------------------- */
/* 2nd stage information */
struct drv6700_info {
   /* filled in by the driver? */
   uint32_t interrupt_msi_dsp_to_host_response;
   uint32_t interrupt_msi_dsp_to_host_stream_data;

   /* filled in by uboot. this interrupt is generated by a slave mode
    * write by the host to DM814x's MSI interrupt register
    */
   uint32_t interrupt_msi_host_to_dsp_message;
};

/* ----------------------- */


#define C6700_INFO_MAGIC_OFFSET \
	(offsetof(struct fw6700_info_v0, magic))
#define C6700_INFO_MODEL_OFFSET \
	(offsetof(struct fw6700_info_v0, model))
#define C6700_INFO_HWREV1_OFFSET \
	(offsetof(struct fw6700_info_v0, hw_rev1))
#define C6700_INFO_HWREV2_OFFSET \
	(offsetof(struct fw6700_info_v0, hw_rev2))
#define C6700_INFO_ERRORCODE_OFFSET \
	(offsetof(struct fw6700_info_v0, error_code))
#define C6700_INFO_STATE_OFFSET \
	(offsetof(struct fw6700_info_v0, state))
#define C6700_INFO_PCIE64BIT_OFFSET \
	(offsetof(struct fw6700_info_v0, pcie64bit))
#define C6700_INFO_HALTARM_OFFSET \
	(offsetof(struct fw6700_info_v0, haltarm))
#define C6700_INFO_SOCPHYMEMSTARTADDR_OFFSET \
	(offsetof(struct fw6700_info_v0, soc_phymem_start_addr))
#define C6700_INFO_SOCPHYMEMSIZE_OFFSET \
	(offsetof(struct fw6700_info_v0, soc_phymem_size))
#define C6700_INFO_DRVINFOSIZE_OFFSET \
	(offsetof(struct fw6700_info_v0, drvinfo_size))
#define C6700_INFO_DRVINFOADDR_OFFSET \
	(offsetof(struct fw6700_info_v0, drvinfo_addr))
#define C6700_INFO_ENTRYPOINTADDR_OFFSET \
	(offsetof(struct fw6700_info_v0, entrypoint_addr))

/***********************************************************
Types used for mixer control caching
************************************************************/
#define HPI_NMIXER_CONTROLS 2048

/***********************************************************
The Host located memory buffer that the 6700 will bus master
in and out of.
************************************************************/
#define HPI6700_SIZEOF_DATA (16*1024)
#define HPI6700_MSG_ALIGN (2048)
#define HPI6700_RSP_ALIGN (2048)

struct message_buffer_6700 {
	struct hpi_message message;
	char data[1];
};

struct response_buffer_6700 {
	struct hpi_response response;
	char data[1];
};

union padded_message_buffer_6700 {
	struct message_buffer_6700 MessageBuffer;
	uint8_t bData[HPI6700_MSG_ALIGN - sizeof(uint32_t)];
};

union padded_response_buffer_6700 {
	struct response_buffer_6700 ResponseBuffer;
	uint8_t bData[HPI6700_RSP_ALIGN - sizeof(uint32_t)];
};

/*********************************************************************
 * Used for dynamic control cache allocation
 *********************************************************************/
struct controlcache_6700 {
	uint32_t dwNumberOfControls;
	uint32_t dwPhysicalAddress32;
	uint32_t dwSizeInBytes;
	uint32_t padding;
};

/*********************************************************************
 * Used for dynamic allocation of async event array
 *********************************************************************/
struct async_event_buffer_6700 {
	uint32_t dwPhysicalAddress32;
	uint32_t dwSpare;
	struct hpi_fifo_buffer b;
};

#define BMI67_FLAGS_NOMESSAGEIRQ	(0x00000001)

struct bus_master_interface_67 {
	uint32_t dwMagic;
	uint32_t dwDSPStreamInterruptCount;
	uint32_t dwFlags;
	uint32_t dwTransferSizeInBytes;
	uint32_t reserved[4];				// for future use

	// The following must start on a 16 byte boundary
	uint32_t dwHostCmdCount;
	union padded_message_buffer_6700 msg;

	uint32_t dwDspAckCount;
	union padded_response_buffer_6700 rsp;

	struct controlcache_6700 aControlCache;

	struct async_event_buffer_6700 aAsyncBuffer;

	struct hpi_hostbuffer_status
		aInStreamHostBufferStatus[HPI_MAX_STREAMS];

	struct hpi_hostbuffer_status
		aOutStreamHostBufferStatus[HPI_MAX_STREAMS];
};

/* Layout of info struct on DSP */
struct fw6700_dsp_info_v0 {
	uint32_t dwMagic;
	uint32_t pInterfaceBuffer;
	uint32_t dwInterfaceBufferSize;
	uint32_t dwDspInfoMagicOk;
	uint32_t dwBusMasterMagicOk;
	uint32_t dwDspReady;
};

#define C6700_DSP_INFO_MAGIC_OFFSET \
	(offsetof(struct fw6700_dsp_info_v0, dwMagic))
#define C6700_DSP_INFO_INTERFACEBUFFER_OFFSET \
	(offsetof(struct fw6700_dsp_info_v0, pInterfaceBuffer))
#define C6700_DSP_INFO_INTERFACEBUFFERSIZE_OFFSET \
	(offsetof(struct fw6700_dsp_info_v0, dwInterfaceBufferSize))
#define C6700_DSP_INFO_DSPINFOMAGICOK_OFFSET \
	(offsetof(struct fw6700_dsp_info_v0, dwDspInfoMagicOk))
#define C6700_DSP_INFO_BUSMASTERMAGICOK_OFFSET \
	(offsetof(struct fw6700_dsp_info_v0, dwBusMasterMagicOk))
#define C6700_DSP_INFO_DSPREADY_OFFSET \
	(offsetof(struct fw6700_dsp_info_v0, dwDspReady))

#define C6700_BAR0_CMD_STATUS       (0x004)
#define OB_XLT_EN                   (2)
#define C6700_BAR0_GPR0             (0x070)
#define C6700_BAR0_GPR1             (0x074)
#define C6700_BAR0_GPR2             (0x078)
#define C6700_BAR0_GPR3             (0x07c)
#define C6700_BAR0_MSI_IRQ          (0x054)
#define C6700_BAR0_MSI_IRQ_STATUS   (0x104)
#define C6700_IB_BAR(n)             (0x300 + (n) * 0x10)
#define C6700_IB_START_LO(n)        (C6700_IB_BAR(n) + 0x4)
#define C6700_IB_START_HI(n)        (C6700_IB_BAR(n) + 0x8)
#define C6700_IB_OFFSET(n)          (C6700_IB_BAR(n) + 0xC)
