/*************************************************************************
*
*                  Copyright 2012 Mentor Graphics Corporation
*                         All Rights Reserved.
*
* THIS WORK CONTAINS TRADE SECRET AND PROPRIETARY INFORMATION WHICH IS THE
* PROPERTY OF MENTOR GRAPHICS CORPORATION OR ITS LICENSORS AND IS SUBJECT
* TO LICENSE TERMS.
*
**************************************************************************

**************************************************************************
* FILE NAME
*
*       lwspi.h
*
* COMPONENT
*
*       Nucleus lightweight SPI
*
* DESCRIPTION
*
*       This file contains data structures and APIs provided with
*       Nucleus lightweitht SPI.
*
* DATA STRUCTURES
*
*       NU_SPI_BUS                          SPI bus control block.
*       NU_SPI_DEVICE                       SPI slave control block.
*       NU_SPI_IRP                          I/O request packet.
*       NU_SPI_HANDLE                       SPI slave handle.
*
* DEPENDENCIES
*
*       nucleus.h
*       nu_kernel.h
*
*************************************************************************/
#ifndef _LWSPI_H
#ifdef  __cplusplus
extern  "C" {                               /* C declarations in C++. */
#endif

#define _LWSPI_H

#include    "nucleus.h"
#include    "kernel/nu_kernel.h"

/* LWSPI GUID */
#define LWSPI_LABEL {0xe0,0x76,0xe3,0x6f,0xd9,0xad,0x43,0x85,0xbc,0x5b,0xe3,0x8b,0xe6,0x99,0xfc,0x20}

#define NU_SPI_BUS_NAME_LEN         8

/* Definitions for number of SPI buses and slaves on each bus and 
 * other configurations.
 */
#define LWSPI_NUM_BUSES             CFG_NU_OS_CONN_LWSPI_NUM_SPI_BUSES
#define LWSPI_NUM_SLAVES            CFG_NU_OS_CONN_LWSPI_NUM_SPI_SLAVES
#define LWSPI_ERR_CHECK_ENABLE      CFG_NU_OS_CONN_LWSPI_ERR_CHECK_ENABLE
#define LWSPI_INT_MODE_IO_ENABLE    CFG_NU_OS_CONN_LWSPI_INT_MODE_IO_ENABLE

/* LWSPI specific error codes. */
#define NU_SPI_INVLD_ARG                        -4000
#define NU_SPI_NO_FREE_BUS_SLOT                 -4001
#define NU_SPI_NO_FREE_SLAVE_SLOT               -4002
#define NU_SPI_BUS_SLOT_NOT_FOUND               -4003
#define NU_SPI_INVLD_IO_PTR                     -4004

/* Defines for SPI modes. */
#define SPI_MODE_POL_LO_PHA_LO                  (0UL << 16)
#define SPI_MODE_POL_LO_PHA_HI                  (1UL << 16)
#define SPI_MODE_POL_HI_PHA_LO                  (2UL << 16)
#define SPI_MODE_POL_HI_PHA_HI                  (3UL << 16)

/* Definitions for I/O types. */
#define SPI_POLLED_IO                           0
#define SPI_INTERRUPT_IO                        NU_SUSPEND

/* Definitions for bit order. */
#define SPI_BO_LSB_FIRST                        (0UL << 8)
#define SPI_BO_MSB_FIRST                        (1UL << 8)

/* Definitions for slave select polarity. */
#define SPI_SS_POL_LO                           0
#define SPI_SS_POL_HI                           1
#define SPI_SS_POL_DONT_CARE                    2

/* Lightweight SPI IOCTLs. */
#define LWSPI_IOCTL_GET_BUS_INFO                0
#define LWSPI_NUM_IOCTLS                        1

typedef struct _nu_spi_bus          NU_SPI_BUS;
typedef struct _nu_spi_device       NU_SPI_DEVICE;
typedef struct _nu_spi_irp          NU_SPI_IRP;
typedef struct _nu_spi_io_ptrs      NU_SPI_IO_PTRS;
typedef UINT32                      NU_SPI_HANDLE;
typedef VOID (*SPI_SS_CALLBACK)(BOOLEAN);

struct _nu_spi_irp
{
    NU_SPI_DEVICE       *device;
    UINT8               *buffer;
    UINT32              length;
    UINT32              actual_length;
};

struct _nu_spi_device
{
    NU_SPI_IRP          tx_irp;
    NU_SPI_IRP          rx_irp;
    NU_SEMAPHORE        async_io_lock;
    SPI_SS_CALLBACK     ss_callback;
    UINT32              baud_rate;
    UINT32              max_transfer_size;
    NU_SPI_HANDLE       handle;
    NU_SPI_BUS          *bus;
    UINT32              spi_mode;
    UINT32              bit_order;
    UINT32              ss_polarity;
    UINT8               index;
    UINT8               ss_index;
};

struct _nu_spi_io_ptrs
{
    VOID (*configure)(VOID*, NU_SPI_DEVICE*);
    VOID (*check_power_on)(VOID*);
    BOOLEAN (*isr_read)(VOID*, NU_SPI_IRP*);
    BOOLEAN (*isr_write)(VOID*, NU_SPI_IRP*);
    BOOLEAN (*isr_write_read)(VOID*, NU_SPI_IRP*, NU_SPI_IRP*);
    STATUS (*read)(VOID*, BOOLEAN, NU_SPI_IRP*);
    STATUS (*write)(VOID*, BOOLEAN, NU_SPI_IRP*);
    STATUS (*write_read)(VOID*, BOOLEAN, NU_SPI_IRP*, NU_SPI_IRP*);
};
  
struct _nu_spi_bus
{
    NU_SEMAPHORE        bus_lock;
    NU_SPI_IO_PTRS      io_ptrs;
    CHAR                name[NU_SPI_BUS_NAME_LEN + 1];
    NU_SPI_DEVICE       *slaves[LWSPI_NUM_SLAVES];
#if (LWSPI_NUM_SLAVES > 1)
    NU_SPI_DEVICE       *current_slave;
#endif
    VOID                *dev_context;
    DV_DEV_HANDLE       dev_handle;
    DV_DEV_ID           dev_id;
    INT                 ioctl_base;
    BOOLEAN             is_used;
    UINT8               index;
    UINT8               pad[2];
};

STATUS NU_SPI_Register_Slave(CHAR*, UINT32, UINT32, UINT32, 
                            SPI_SS_CALLBACK, NU_SPI_HANDLE*);
STATUS NU_SPI_Unregister_Slave(NU_SPI_HANDLE);
STATUS NU_SPI_Read(NU_SPI_HANDLE, UNSIGNED, UINT8*, UINT32);
STATUS NU_SPI_Write(NU_SPI_HANDLE, UNSIGNED, UINT8*, UINT32);
STATUS NU_SPI_Write_Read(NU_SPI_HANDLE, UNSIGNED, UINT8*, UINT8*, UINT32);

#if (CFG_NU_OS_CONN_LWSPI_EXTENDED_API_ENABLE == NU_TRUE)
STATUS NU_SPI_Set_Slave_Select_Index(NU_SPI_HANDLE, UINT8);
#endif /* (CFG_NU_OS_CONN_LWSPI_EXTENDED_API_ENABLE == NU_TRUE) */

#ifdef      __cplusplus
}
#endif
#endif  /* #ifndef _LWSPI_H */
