fsata.h 9.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
/*
 * 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