277 lines
9.3 KiB
C
277 lines
9.3 KiB
C
|
/*
|
|||
|
* Copyright : (C) 2022 Phytium Information Technology, Inc.
|
|||
|
* All Rights Reserved.
|
|||
|
*
|
|||
|
* This program is OPEN SOURCE software: you can redistribute it and/or modify it
|
|||
|
* under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
|
|||
|
* either version 1.0 of the License, or (at your option) any later version.
|
|||
|
*
|
|||
|
* 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 Phytium Public License for more details.
|
|||
|
*
|
|||
|
*
|
|||
|
* FilePath: fsata.h
|
|||
|
* Date: 2022-02-10 14:55:11
|
|||
|
* LastEditTime: 2022-02-18 09:05:24
|
|||
|
* Description: This files is for sata ctrl function definition
|
|||
|
*
|
|||
|
* Modify History:
|
|||
|
* Ver Who Date Changes
|
|||
|
* ----- ------ -------- --------------------------------------
|
|||
|
*/
|
|||
|
|
|||
|
#ifndef BSP_DRIVERS_FSATA_H
|
|||
|
#define BSP_DRIVERS_FSATA_H
|
|||
|
|
|||
|
#ifdef __cplusplus
|
|||
|
extern "C"
|
|||
|
{
|
|||
|
#endif
|
|||
|
/***************************** Include Files *********************************/
|
|||
|
#include "ftypes.h"
|
|||
|
#include "ferror_code.h"
|
|||
|
#include "fkernel.h"
|
|||
|
|
|||
|
#define FSATA_SUCCESS FT_SUCCESS
|
|||
|
#define FSATA_ERR_INVAILD_PARAMETER FT_MAKE_ERRCODE(ErrModBsp, ErrBspSata, 1)
|
|||
|
#define FSATA_ERR_TIMEOUT FT_MAKE_ERRCODE(ErrModBsp, ErrBspSata, 2)
|
|||
|
#define FSATA_ERR_OPERATION FT_MAKE_ERRCODE(ErrModBsp, ErrBspSata, 3)
|
|||
|
#define FSATA_UNKNOWN_DEVICE FT_MAKE_ERRCODE(ErrModBsp, ErrBspSata, 4)
|
|||
|
|
|||
|
/************************** Constant Definitions *****************************/
|
|||
|
#define FSATA_AHCI_MAX_PORTS 32
|
|||
|
#define FSATA_AHCI_MAX_PRD_ENTRIES 16
|
|||
|
|
|||
|
#define MAX_DATA_BYTE_COUNT SZ_4M
|
|||
|
|
|||
|
#define FSATA_AHCI_CMD_LIST_HEADER_SIZE 0x20
|
|||
|
#define FSATA_AHCI_CMD_LIST_HEADER_NUM 32
|
|||
|
#define FSATA_AHCI_RX_FIS_SZ 0x100
|
|||
|
#define FSATA_AHCI_CMD_TABLE_HEADER_SIZE 0x80
|
|||
|
#define FSATA_AHCI_PRTD_ITEM_SIZE 0x10
|
|||
|
#define FSATA_AHCI_PRTD_ITEM_NUM 0x40 /*set 64 item, hardware max is 64K */
|
|||
|
|
|||
|
#define FSATA_AHCI_CMD_TABLE_SIZE (FSATA_AHCI_CMD_TABLE_HEADER_SIZE + (FSATA_AHCI_PRTD_ITEM_NUM * FSATA_AHCI_PRTD_ITEM_SIZE))
|
|||
|
#define FSATA_AHCI_PORT_PRIV_DMA_SZ (FSATA_AHCI_CMD_LIST_HEADER_SIZE * FSATA_AHCI_CMD_LIST_HEADER_NUM + \
|
|||
|
FSATA_AHCI_CMD_TABLE_SIZE + FSATA_AHCI_RX_FIS_SZ)
|
|||
|
|
|||
|
#define FSATA_AHCI_CMD_ATAPI BIT(5)
|
|||
|
#define FSATA_AHCI_CMD_WRITE BIT(6)
|
|||
|
#define FSATA_AHCI_CMD_PREFETCH BIT(7)
|
|||
|
#define FSATA_AHCI_CMD_RESET BIT(8)
|
|||
|
#define FSATA_AHCI_CMD_CLR_BUSY BIT(10)
|
|||
|
|
|||
|
#define FSATA_ID_LBA48_SECTORS 100
|
|||
|
#define FSATA_ID_LBA_SECTORS 60
|
|||
|
|
|||
|
#define FSATA_ID_ATA_DEVICE BIT(15) /* IDENTIFY DEVICE word 0, if ATA device */
|
|||
|
#define FSATA_ID_COMPLETE BIT(2) /* IDENTIFY DEVICE word 0, if the content of the IDENTIFY DEVICE data is incomplete */
|
|||
|
|
|||
|
#define FSATA_ID_FW_REV 23 /* firmware revision position */
|
|||
|
#define FSATA_ID_PROD 27 /* Model number position */
|
|||
|
#define FSATA_ID_WORDS 256 /* IDENTIFY DEVICE data length */
|
|||
|
|
|||
|
enum
|
|||
|
{
|
|||
|
FSATA_FIS_REG_HOST_TO_DEVICE = 0x27,
|
|||
|
FSATA_FIS_REG_DEVICE_TO_HOST = 0x34,
|
|||
|
FSATA_FIS_DMA_SETUP = 0x41
|
|||
|
};
|
|||
|
|
|||
|
#define FSATA_FIS_REG_HOST_TO_DEVICE_C BIT(7) /* update of the command register */
|
|||
|
#define FSATA_CMD_EXT_DEVICE BIT(6) /* command device byte requirement */
|
|||
|
|
|||
|
enum
|
|||
|
{
|
|||
|
FSATA_CMD_READ_EXT = 0x25,
|
|||
|
FSATA_CMD_WRITE_EXT = 0x35,
|
|||
|
FSATA_CMD_IDENTIFY_DEVICE = 0xEC,
|
|||
|
FSATA_CMD_FPDMA_READ = 0x60,
|
|||
|
FSATA_CMD_FPDMA_WRITE = 0x61
|
|||
|
};
|
|||
|
|
|||
|
#define FSATA_BUSY BIT(7) /* BSY status bit */
|
|||
|
|
|||
|
#define FSATA_SECT_SIZE 512 /* sata sector size */
|
|||
|
|
|||
|
#define FSATA_BLK_VEN_SIZE 40 /* device vendor string size */
|
|||
|
#define FSATA_BLK_PRD_SIZE 20 /* device product number size */
|
|||
|
#define FSATA_BLK_REV_SIZE 8 /* firmware revision size */
|
|||
|
|
|||
|
#define FSATA_DEV_TYPE_UNKNOWN 0xff /* not connected */
|
|||
|
#define FSATA_DEV_TYPE_HARDDISK 0x00 /* harddisk */
|
|||
|
|
|||
|
#define FSATA_IF_TYPE_UNKNOWN 0xff
|
|||
|
#define FSATA_IF_TYPE_SCSI 0x00
|
|||
|
|
|||
|
enum
|
|||
|
{
|
|||
|
FSATA_TYPE_PCIE = 0,
|
|||
|
FSATA_TYPE_CONTROLLER = 1
|
|||
|
};
|
|||
|
|
|||
|
/************************** Variable Definitions *****************************/
|
|||
|
|
|||
|
/***************** Macros (Inline Functions) Definitions *********************/
|
|||
|
|
|||
|
/* Number of User Addressable Logical Sectors lba28 */
|
|||
|
#define FSATA_ID_U32(id,n) \
|
|||
|
(((u32) (id)[(n) + 1] << 16) | ((u32) (id)[(n)]))
|
|||
|
|
|||
|
/* Number of User Addressable Logical Sectors lba48 */
|
|||
|
#define FSATA_ID_U64(id,n) \
|
|||
|
( ((u64) (id)[(n) + 3] << 48) | \
|
|||
|
((u64) (id)[(n) + 2] << 32) | \
|
|||
|
((u64) (id)[(n) + 1] << 16) | \
|
|||
|
((u64) (id)[(n) + 0]) )
|
|||
|
|
|||
|
/* if sata id is support lba */
|
|||
|
#define FSataIdHasLba(id) ((id)[49] & BIT(9))
|
|||
|
|
|||
|
/* if sata id is support lba48 */
|
|||
|
static inline int FSataIdHasLba48(const u16 *id)
|
|||
|
{
|
|||
|
if ((id[83] & 0xC000) != 0x4000)
|
|||
|
return 0;
|
|||
|
if (!FSATA_ID_U64(id, 100))
|
|||
|
return 0;
|
|||
|
return id[83] & BIT(10);
|
|||
|
}
|
|||
|
|
|||
|
/**************************** Type Definitions *******************************/
|
|||
|
typedef void (*FSataIrqCallBack)(void *args);
|
|||
|
|
|||
|
/* sata info */
|
|||
|
typedef struct
|
|||
|
{
|
|||
|
unsigned char if_type; /* type of the interface */
|
|||
|
unsigned char type; /* device type */
|
|||
|
char vendor[FSATA_BLK_VEN_SIZE + 1]; /* device vendor string */
|
|||
|
char product[FSATA_BLK_PRD_SIZE + 1]; /* device product number */
|
|||
|
char revision[FSATA_BLK_REV_SIZE + 1]; /* firmware revision */
|
|||
|
unsigned long lba; /* number of blocks */
|
|||
|
unsigned long lba512; /* number of blocks of 512 bytes */
|
|||
|
unsigned long blksz; /* block size */
|
|||
|
} FSataInfo;
|
|||
|
|
|||
|
/* Received FIS Structure */
|
|||
|
typedef struct __attribute__((__packed__))
|
|||
|
{
|
|||
|
u8 dma_setup_fis[28];
|
|||
|
u8 reserved0[4];
|
|||
|
u8 pio_setup_fis[20];
|
|||
|
u8 reserved1[12];
|
|||
|
u8 d2h_register_fis[20];
|
|||
|
u8 reserved2[4];
|
|||
|
u8 set_device_bits_fis[8];
|
|||
|
u8 unknown_fis[64];
|
|||
|
u8 reserved3[96];
|
|||
|
}
|
|||
|
FSataAhciRecvFis;
|
|||
|
|
|||
|
/* command list structure - command header */
|
|||
|
typedef struct
|
|||
|
{
|
|||
|
u32 description_info;/* DW 0 – Description Information */
|
|||
|
u32 status; /* DW 1 - Command Status */
|
|||
|
u32 tbl_addr; /* DW 2 – Command Table Base Address */
|
|||
|
u32 tbl_addr_hi; /* DW 3 – Command Table Base Address Upper */
|
|||
|
u32 reserved[4];
|
|||
|
} FSataAhciCommandList;
|
|||
|
|
|||
|
/* command table - PRDT */
|
|||
|
typedef struct
|
|||
|
{
|
|||
|
u32 addr_low; /* DW 0 – Data Base Address */
|
|||
|
u32 addr_high; /* DW 1 – Data Base Address Upper */
|
|||
|
u32 reserved; /* DW 2 – Reserved */
|
|||
|
u32 data_byte; /* DW 3 – Description Information */
|
|||
|
} FSataAhciCommandTablePrdt;
|
|||
|
|
|||
|
/* ahci port information structure */
|
|||
|
typedef struct
|
|||
|
{
|
|||
|
uintptr port_base_addr; /* port base address */
|
|||
|
FSataAhciCommandList *cmd_list; /* Command List structure, will include cmd_tbl's address */
|
|||
|
FSataAhciRecvFis *rx_fis; /* Received FIS Structure */
|
|||
|
uintptr cmd_tbl_base_addr; /* command table addr, also the command table's first part */
|
|||
|
FSataAhciCommandTablePrdt *cmd_tbl_prdt;/* command table's second part , cmd_tbl + cmd_tbl_prdt = command table*/
|
|||
|
FSataInfo dev_info;
|
|||
|
} FSataAhciPorts;
|
|||
|
|
|||
|
typedef struct
|
|||
|
{
|
|||
|
u32 instance_id; /* Device instance id */
|
|||
|
uintptr base_addr; /* sata base address */
|
|||
|
char *instance_name; /* instance name */
|
|||
|
u32 irq_num; /* Irq number */
|
|||
|
} FSataConfig; /* sata config */
|
|||
|
|
|||
|
typedef struct
|
|||
|
{
|
|||
|
FSataConfig config;
|
|||
|
u32 is_ready;
|
|||
|
|
|||
|
FSataAhciPorts port[FSATA_AHCI_MAX_PORTS];
|
|||
|
u16 *ataid[FSATA_AHCI_MAX_PORTS];
|
|||
|
u32 n_ports; /* maximum number of ports supported by the ahci, Number of Ports (NP)*/
|
|||
|
u32 port_map; /* each bit indicate port can be used, If a bit is set to ‘1’, the corresponding port is available for software to use. */
|
|||
|
u32 link_port_map; /* each bit indicate port linkup sata device */
|
|||
|
u32 private_data; /* each bit indicate port sata achi started */
|
|||
|
|
|||
|
FSataIrqCallBack fsata_dhrs_cb; /* device-to-host register fis interrupt */
|
|||
|
void *dhrs_args;
|
|||
|
FSataIrqCallBack fsata_pss_cb; /* pio setup fis interrupt */
|
|||
|
void *pss_args;
|
|||
|
FSataIrqCallBack fsata_dss_cb; /* dma setup fis interrupt */
|
|||
|
void *dss_args;
|
|||
|
FSataIrqCallBack fsata_sdbs_cb; /* set device bits interrupt */
|
|||
|
void *sdbs_args;
|
|||
|
FSataIrqCallBack fsata_pcs_cb; /* port connect change status interrupt */
|
|||
|
void *pcs_args;
|
|||
|
|
|||
|
volatile u8 dhrs_flag;
|
|||
|
volatile u8 sdb_flag;
|
|||
|
} FSataCtrl;
|
|||
|
|
|||
|
|
|||
|
/************************** Function Prototypes ******************************/
|
|||
|
|
|||
|
/* sata config init */
|
|||
|
const FSataConfig *FSataLookupConfig(u32 instance_id, u8 type);
|
|||
|
|
|||
|
/* initialize sata ctrl */
|
|||
|
FError FSataCfgInitialize(FSataCtrl *instance_p, const FSataConfig *input_config_p);
|
|||
|
|
|||
|
/* deinitialize sata ctrl */
|
|||
|
void FSataCfgDeInitialize(FSataCtrl *pctrl);
|
|||
|
|
|||
|
/* read sata info */
|
|||
|
FError FSataAhciReadInfo(FSataCtrl *instance_p, u8 port);
|
|||
|
|
|||
|
/* init ahci */
|
|||
|
FError FSataAhciInit(FSataCtrl *instance_p);
|
|||
|
|
|||
|
/* init ahci port */
|
|||
|
FError FSataAhciPortStart(FSataCtrl *instance_p, u8 port, uintptr mem);
|
|||
|
|
|||
|
/* read or write sata data */
|
|||
|
FError FSataReadWrite(FSataCtrl *instance_p, u8 port, u32 start,
|
|||
|
u16 blk_cnt, u8 *buffer, boolean is_ncq, boolean is_write);
|
|||
|
|
|||
|
/* sata all irq handler entry */
|
|||
|
void FSataIrqHandler(s32 vector, void *param);
|
|||
|
|
|||
|
/* set specific sata irq function entry */
|
|||
|
FError FSataSetHandler(FSataCtrl *instance_p, u32 handler_type,
|
|||
|
void *func_pointer, void *call_back_ref);
|
|||
|
|
|||
|
/* set sata irq mask */
|
|||
|
void FSataIrqEnable(FSataCtrl *instance_p, u32 int_mask);
|
|||
|
|
|||
|
#ifdef __cplusplus
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
#endif
|