/* * 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