1 /*
2  * Copyright (c) 2021-2022 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #ifndef _HPM_FEMC_DRV_H
9 #define _HPM_FEMC_DRV_H
10 #include "hpm_femc_regs.h"
11 
12 /**
13  * @brief femc driver APIs
14  * @defgroup dram_interface femc driver APIs
15  * @ingroup io_interfaces
16  * @{
17  *
18  */
19 
20 #define FEMC_SDRAM_MAX_BURST_LENGTH_IN_BYTE (8UL)
21 /* @brief femc sdram column address bit width */
22 #define FEMC_SDRAM_COLUMN_ADDR_12_BITS (0U)
23 #define FEMC_SDRAM_COLUMN_ADDR_11_BITS (1U)
24 #define FEMC_SDRAM_COLUMN_ADDR_10_BITS (2U)
25 #define FEMC_SDRAM_COLUMN_ADDR_9_BITS (3U)
26 #define FEMC_SDRAM_COLUMN_ADDR_8_BITS (4U)
27 /* @brief cas latency */
28 #define FEMC_SDRAM_CAS_LATENCY_1 (1U)
29 #define FEMC_SDRAM_CAS_LATENCY_2 (2U)
30 #define FEMC_SDRAM_CAS_LATENCY_3 (3U)
31 /* @brief iomux options */
32 #define FEMC_IO_MUX_NOT_USED (0U)
33 #define FEMC_IO_MUX_CSX0 (1U)
34 #define FEMC_IO_MUX_CSX1 (2U)
35 #define FEMC_IO_MUX_CSX2 (3U)
36 #define FEMC_IO_MUX_CSX3 (4U)
37 #define FEMC_IO_MUX_RDY (5U)
38 /* @brief sdram bank number */
39 #define FEMC_SDRAM_BANK_NUM_4 (0U)
40 #define FEMC_SDRAM_BANK_NUM_2 (1U)
41 /* @brief chip select */
42 #define FEMC_SDRAM_CS0 (0U)
43 #define FEMC_SDRAM_CS1 (1U)
44 /* @brief sdram port size */
45 #define FEMC_SDRAM_PORT_SIZE_8_BITS (0U)
46 #define FEMC_SDRAM_PORT_SIZE_16_BITS (1U)
47 #define FEMC_SDRAM_PORT_SIZE_32_BITS (2U)
48 
49 #define FEMC_AXI_Q_COUNT (2U)
50 #define FEMC_AXI_Q_A (0U)
51 #define FEMC_AXI_Q_B (1U)
52 /* @brief DQS option */
53 #define FEMC_DQS_INTERNAL (0U)
54 #define FEMC_DQS_FROM_PAD (1U)
55 
56 #define FEMC_BR_COUNT (2U)
57 
58 #define FEMC_CMD_KEY                   FEMC_IPCMD_KEY_SET(0xA55A)
59 #define FEMC_CMD_WRITE_FLAG            (1UL << 31)
60 #define FEMC_CMD_SDRAM_READ            (0x8U)
61 #define FEMC_CMD_SDRAM_WRITE           (FEMC_CMD_WRITE_FLAG | 0x9U)
62 #define FEMC_CMD_SDRAM_MODE_SET        (FEMC_CMD_WRITE_FLAG | 0xAU)
63 #define FEMC_CMD_SDRAM_ACTIVE          (0xBU)
64 #define FEMC_CMD_SDRAM_AUTO_REFRESH    (0xCU)
65 #define FEMC_CMD_SDRAM_SELF_REFRESH    (0xDU)
66 #define FEMC_CMD_SDRAM_PRECHARGE       (0xEU)
67 #define FEMC_CMD_SDRAM_PRECHARGE_ALL   (0xFU)
68 
69 /* @brief sram address mode */
70 #define FEMC_SRAM_AD_MUX_MODE (0U)
71 #define FEMC_SRAM_AD_NONMUX_MODE (3U)
72 
73 /* @brief sram adv hold state */
74 #define FEMC_SRAM_ADV_HOLD_HIGH (0U)
75 #define FEMC_SRAM_ADV_HOLD_LOW (1U)
76 
77 /* @brief sram adv polarity */
78 #define FEMC_SRAM_ADV_ACTIVE_LOW (0U)
79 #define FEMC_SRAM_ADV_ACTIVE_HIGH (1U)
80 
81 /* @brief sram port size */
82 #define FEMC_SRAM_PORT_SIZE_8_BITS (0U)
83 #define FEMC_SRAM_PORT_SIZE_16_BITS (1U)
84 
85 /* @brief IO_CSX selection */
86 #define FEMC_IO_CSX_SDRAM_CS1 (1U)
87 #define FEMC_IO_CSX_SRAM_CE (6U)
88 
89 /**
90  * @brief Structure for specifying the configuration of AXI queue weight
91  */
92 typedef struct {
93     bool enable;                /**< Enable AXI weight setting flag */
94     uint8_t qos;
95     uint8_t age;
96     uint8_t slave_hit_wo_rw;
97     uint8_t slave_hit;          /**< only available for queue A */
98     uint8_t page_hit;           /**< only available for queue B */
99     uint8_t bank_rotation;      /**< only available for queue B */
100 } femc_axi_q_weight_t;
101 
102 /**
103  * @brief Structure for specifying the configuration of SDRAM
104  */
105 typedef struct {
106     uint32_t base_address;              /**< external SDRAM base address */
107     uint32_t size_in_byte;              /**< external SDRAM size in byte */
108     uint32_t refresh_count;             /**< referesh count */
109     uint8_t col_addr_bits;              /**< column address bit count */
110     uint8_t cas_latency;                /**< CAS latency */
111     uint8_t cs;                         /**< chip select */
112     uint8_t cs_mux_pin;                 /**< chip select mux */
113     uint8_t bank_num;                   /**< bank number */
114     uint8_t prescaler;                  /**< presecaler */
115     uint8_t port_size;                  /**< SDRAM port size */
116     uint8_t burst_len_in_byte;          /**< 1/2/4/8 bytes */
117     uint8_t cke_off_in_ns;
118     uint8_t act_to_precharge_in_ns;     /**< Tras */
119     uint8_t precharge_to_act_in_ns;     /**< Trp  */
120     uint8_t act_to_rw_in_ns;            /**< Trcd */
121     uint8_t act_to_act_in_ns;           /**< Trrd */
122     uint8_t refresh_to_refresh_in_ns;   /**< Trc */
123     uint8_t write_recover_in_ns;        /**< Twr */
124     uint8_t self_refresh_recover_in_ns; /**< Txsr */
125     uint8_t refresh_recover_in_ns;      /**< Trc */
126     uint8_t refresh_in_ms;              /**< Tref */
127     uint8_t idle_timeout_in_ns;
128     uint8_t cmd_data_width;
129     uint8_t auto_refresh_count_in_one_burst;
130     bool delay_cell_disable;            /**< Delay cell disable */
131     uint8_t delay_cell_value;           /**< Delay cell value */
132 } femc_sdram_config_t;
133 
134 /**
135  * @brief Structure for specifying the configuration of SRAM
136  */
137 typedef struct {
138     uint32_t base_address;              /**< external SRAM base address */
139     uint32_t size_in_byte;              /**< external SRAM size in byte */
140     uint8_t address_mode;               /**< address mode */
141     uint8_t port_size;                  /**< port size */
142     uint8_t adv_hold_state;             /**< adv hold level */
143     uint8_t adv_polarity;               /**< adv polarity */
144     uint8_t oeh_in_ns;                  /**< OE high time */
145     uint8_t oel_in_ns;                  /**< OE low time */
146     uint8_t weh_in_ns;                  /**< WE high time */
147     uint8_t wel_in_ns;                  /**< WE low time */
148     uint8_t ah_in_ns;                   /**< address hold time */
149     uint8_t as_in_ns;                   /**< address setup time */
150     uint8_t ceh_in_ns;                  /**< chip enable hold time */
151     uint8_t ces_in_ns;                  /**< chip enable setup time */
152 } femc_sram_config_t;
153 
154 /**
155  * @brief Structure for specifying the configuration of FEMC
156  */
157 typedef struct {
158     uint8_t dqs;                        /**< DQS setting */
159     uint8_t cmd_timeout;                /**< command timeout */
160     uint8_t bus_timeout;                /**< bus timeout */
161     femc_axi_q_weight_t axi_q_weight[FEMC_AXI_Q_COUNT];
162 } femc_config_t;
163 
164 /**
165  * @brief Structure for FEMC command
166  */
167 typedef struct {
168     uint32_t opcode;
169     uint32_t data;
170 } femc_cmd_t;
171 
172 /*
173  * @brief FEMC specific status
174  */
175 enum {
176     status_femc_cmd_err = MAKE_STATUS(status_group_femc, 1),
177 };
178 
179 #ifdef __cplusplus
180 extern "C" {
181 #endif
182 
183 /**
184  * @brief femc enable
185  *
186  * Enable FEMC
187  *
188  * @param[in] ptr FEMC base address
189  */
femc_enable(FEMC_Type * ptr)190 static inline void femc_enable(FEMC_Type *ptr)
191 {
192     ptr->CTRL &= ~FEMC_CTRL_DIS_MASK;
193 }
194 
195 /**
196  * @brief femc disable
197  *
198  * Disable FEMC
199  *
200  * @param[in] ptr FEMC base address
201  */
femc_disable(FEMC_Type * ptr)202 static inline void femc_disable(FEMC_Type *ptr)
203 {
204     while ((ptr->STAT0 & (uint32_t) FEMC_STAT0_IDLE_MASK) == 0) {
205     }
206     ptr->CTRL |= FEMC_CTRL_DIS_MASK;
207 }
208 
209 /**
210  * @brief femc software reset
211  *
212  * Perform software reset
213  *
214  * @param[in] ptr FEMC base address
215  */
femc_sw_reset(FEMC_Type * ptr)216 static inline void femc_sw_reset(FEMC_Type *ptr)
217 {
218     ptr->CTRL = FEMC_CTRL_RST_MASK;
219     while ((ptr->CTRL & (uint32_t) FEMC_CTRL_RST_MASK) != 0) {
220     }
221 }
222 
223 /**
224  * @brief femc get default config
225  *
226  * Get FEMC default parameters
227  *
228  * @param[in] ptr FEMC base address
229  * @param[out] config femc_config_t address
230  */
231 void femc_default_config(FEMC_Type *ptr, femc_config_t *config);
232 
233 /**
234  * @brief femc init controller
235  *
236  * Initialize FEMC with give femc_config_t
237  *
238  * @param[in] ptr FEMC base address
239  * @param[in] config femc_config_t to initialize femc
240  */
241 void femc_init(FEMC_Type *ptr, femc_config_t *config);
242 
243 /**
244  * @brief femc get typical sdram config
245  *
246  * Fill out the structure of femc_sdram_config_t with typical SDRAM parameters which should work
247  * with most SDRAMs.
248  *
249  * @param[in] ptr FEMC base address
250  * @param[out] config femc_sdram_config_t sdram configuration struction to config femc
251  */
252 void femc_get_typical_sdram_config(FEMC_Type *ptr, femc_sdram_config_t *config);
253 
254 /**
255  * @brief femc config sdram
256  *
257  * Configure FEMC controlling external SDRAM using parameters specified in femc_sdram_config_t
258  *
259  * @param[in] ptr FEMC base address
260  * @param[in] clk_in_hz femc source clock frequency in Hz
261  * @param[in] config femc_sdram_config_t sdram configuration struction to config femc
262  */
263 hpm_stat_t femc_config_sdram(FEMC_Type *ptr, uint32_t clk_in_hz, femc_sdram_config_t *config);
264 
265 /**
266  * @brief femc get typical sram config
267  *
268  * Fill out the structure of femc_sram_config_t with typical SRAM parameters which should work
269  * with most SRAMs.
270  *
271  * @param[in] ptr FEMC base address
272  * @param[out] config femc_sdram_config_t sdram configuration struction to config femc
273  */
274 void femc_get_typical_sram_config(FEMC_Type *ptr, femc_sram_config_t *config);
275 
276 /**
277  * @brief femc config sram
278  *
279  * Configure FEMC controlling external SRAM using parameters specified in femc_sram_config_t
280  *
281  * @param[in] ptr FEMC base address
282  * @param[in] clk_in_hz femc source clock frequency in Hz
283  * @param[in] config femc_sram_config_t sram configuration struction to config femc
284  */
285 hpm_stat_t femc_config_sram(FEMC_Type *ptr, uint32_t clk_in_hz, femc_sram_config_t *config);
286 
287 #ifdef __cplusplus
288 }
289 #endif
290 /**
291  * @}
292  */
293 #endif    /* _HPM_FEMC_DRV_H */
294 
295