summaryrefslogtreecommitdiff
path: root/bsp/phytium/libraries/standalone/drivers/sata/fsata/fsata.h
blob: d901b344851fd51e094fcc07fd36f2f7c61dc1e8 (plain)
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