/*
 * SPDX-FileCopyrightText: Copyright (c) 2025 HiFiPhile (Zixun LI)
 * SPDX-FileCopyrightText: Copyright (c) 2025 Ha Thach (tinyusb.org)
 * SPDX-License-Identifier: MIT
 *
 * This file is part of the TinyUSB stack.
 */

#ifndef TUSB_HCD_IP3516_H_
#define TUSB_HCD_IP3516_H_

#ifdef __cplusplus
extern "C" {
#endif

//--------------------------------------------------------------------+
// IP3516 CONFIGURATION & CONSTANTS
//--------------------------------------------------------------------+

#define IP3516_ATL_NUM 32
#define IP3516_PTL_NUM 32

#define IP3516_PTD_TOKEN_OUT 0x00U
#define IP3516_PTD_TOKEN_IN 0x01U
#define IP3516_PTD_TOKEN_SETUP 0x02U

#define IP3516_PTD_EPTYPE_OUT 0x00U
#define IP3516_PTD_EPTYPE_IN 0x01U
#define IP3516_PTD_EPTYPE_SETUP 0x02U

#define IP3516_PTD_MAX_TRANSFER_LENGTH 0x7FFFU

#define IP3516_PTD_DATA_ADDR_MASK 0xFFFFU

#define IP3516_MAX_UFRAME (1UL << 8)

#define IP3516_PERIODIC_TRANSFER_GAP (3U)
#define IP3516_ISO_MULTIPLE_TRANSFER (8U)


//--------------------------------------------------------------------+
// IP3516 PTD Data Structure
//--------------------------------------------------------------------+

// Control Word 1
typedef union {
  uint32_t value;
  struct {
    uint32_t valid    : 1;
    uint32_t next_ptd : 5;
    uint32_t          : 1;
    uint32_t jump     : 1;
    uint32_t uframe   : 8;
    uint32_t mps      : 11;
    uint32_t          : 1;
    uint32_t mult     : 2;
    uint32_t          : 2;
  };
} ptd_ctrl1_t;

TU_VERIFY_STATIC(sizeof(ptd_ctrl1_t) == 4, "size is not correct");

// Control Word 2
typedef union {
  uint32_t value;
  struct {
    uint32_t ep_num   : 4;
    uint32_t dev_addr : 7;
    uint32_t split    : 1;
    uint32_t reload   : 4;
    uint32_t speed    : 2;
    uint32_t hub_port : 7;
    uint32_t hub_addr : 7;
  };
} ptd_ctrl2_t;

TU_VERIFY_STATIC(sizeof(ptd_ctrl2_t) == 4, "size is not correct");

// Data Word
typedef union {
  uint32_t value;
  struct {
    uint32_t xfer_len  : 15;
    uint32_t intr      : 1;
    uint32_t data_addr : 16;
  };
} ptd_data_t;

TU_VERIFY_STATIC(sizeof(ptd_data_t) == 4, "size is not correct");

// State Word
typedef union {
  uint32_t value;
  struct {
    uint32_t xferred_len    : 15;
    uint32_t token          : 2;
    uint32_t ep_type        : 2;
    uint32_t nak_cnt        : 4;
    uint32_t err_cnt        : 2;
    uint32_t data_toggle    : 1;
    uint32_t ping           : 1;
    uint32_t start_complete : 1;
    uint32_t error          : 1;
    uint32_t babble         : 1;
    uint32_t halt           : 1;
    uint32_t active         : 1;
  };
} ptd_state_t;

TU_VERIFY_STATIC(sizeof(ptd_state_t) == 4, "size is not correct");

// Status Word
typedef union {
  uint32_t value;
  struct {
    uint32_t uframe_active : 8;
    uint32_t iso_status0   : 3;
    uint32_t iso_status1   : 3;
    uint32_t iso_status2   : 3;
    uint32_t iso_status3   : 3;
    uint32_t iso_status4   : 3;
    uint32_t iso_status5   : 3;
    uint32_t iso_status6   : 3;
    uint32_t iso_status7   : 3;
  };
} ptd_status_t;

TU_VERIFY_STATIC(sizeof(ptd_status_t) == 4, "size is not correct");

// ATL (Asynchronous Transfer List) structure
typedef volatile struct {
  ptd_ctrl1_t ctrl1;
  ptd_ctrl2_t ctrl2;
  ptd_data_t  data;
  ptd_state_t state;
} ip3516_atl_t;

TU_VERIFY_STATIC(sizeof(ip3516_atl_t) == 16, "size is not correct");

// PTL (Periodic Transfer List) structure
typedef volatile struct {
  ptd_ctrl1_t  ctrl1;
  ptd_ctrl2_t  ctrl2;
  ptd_data_t   data;
  ptd_state_t  state;
  ptd_status_t status;
  union {
    uint32_t value;
    struct {
      uint32_t uframe_complete : 8;
      uint32_t spl_iso_in_0    : 24;
    };
  } iso_in_0;
  uint32_t iso_in_1;
  uint32_t iso_in_2;
} ip3516_ptl_t;

TU_VERIFY_STATIC(sizeof(ip3516_ptl_t) == 32, "size is not correct");

// Proprietary Transfer Descriptor
typedef struct {
  ip3516_ptl_t intr[IP3516_PTL_NUM];
  ip3516_ptl_t iso[IP3516_PTL_NUM];
  ip3516_atl_t atl[IP3516_ATL_NUM];
} ip3516_ptd_t;

#ifdef __cplusplus
}
#endif
#endif /* TUSB_HCD_IP3516_H_ */
