• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include "hpm_common.h"
9 #include "hpm_dram_drv.h"
10 
11 #ifndef HPM_DRAM_DRV_DEFAULT_PRESCALER
12 #define HPM_DRAM_DRV_DEFAULT_PRESCALER (0x3UL)
13 #endif
14 
15 #ifndef HPM_DRAM_DRV_RETRY_COUNT
16 #define HPM_DRAM_DRV_RETRY_COUNT (5000U)
17 #endif
18 
19 #define DRAM_PRESCALER_MAX (256UL)
20 
dram_config_delay_cell(DRAM_Type * ptr,uint32_t delay_cell_value)21 static void dram_config_delay_cell(DRAM_Type *ptr, uint32_t delay_cell_value)
22 {
23     ptr->DLYCFG &= ~DRAM_DLYCFG_OE_MASK;
24     ptr->DLYCFG = DRAM_DLYCFG_DLYSEL_SET(delay_cell_value) | DRAM_DLYCFG_DLYEN_MASK;
25     ptr->DLYCFG |= DRAM_DLYCFG_OE_MASK;
26 }
27 
dram_ip_cmd_done(DRAM_Type * ptr)28 static hpm_stat_t dram_ip_cmd_done(DRAM_Type *ptr)
29 {
30     uint32_t intr_status = 0;
31     uint32_t retry = 0;
32     do {
33         if (retry > HPM_DRAM_DRV_RETRY_COUNT) {
34             break;
35         }
36         retry++;
37         intr_status = ptr->INTR
38             & (uint32_t)(DRAM_INTR_IPCMDDONE_MASK | DRAM_INTR_IPCMDERR_MASK);
39     } while (intr_status == 0);
40 
41     if (retry > HPM_DRAM_DRV_RETRY_COUNT) {
42         return status_timeout;
43     }
44 
45     ptr->INTR |= DRAM_INTR_IPCMDDONE_MASK | DRAM_INTR_IPCMDERR_MASK;
46     if (intr_status & DRAM_INTR_IPCMDERR_MASK) {
47         return status_dram_cmd_err;
48     }
49     return status_success;
50 }
51 
dram_make_cmd(uint32_t opcode)52 static uint32_t dram_make_cmd(uint32_t opcode)
53 {
54     return (opcode & ~DRAM_CMD_WRITE_FLAG) | DRAM_CMD_KEY;
55 }
56 
dram_is_write_cmd(uint32_t opcode)57 static bool dram_is_write_cmd(uint32_t opcode)
58 {
59     return ((opcode & DRAM_CMD_WRITE_FLAG) == DRAM_CMD_WRITE_FLAG);
60 }
61 
dram_issue_ip_cmd(DRAM_Type * ptr,uint32_t base_address,dram_cmd_t * cmd)62 uint32_t dram_issue_ip_cmd(DRAM_Type *ptr, uint32_t base_address, dram_cmd_t *cmd)
63 {
64     bool read_data = !dram_is_write_cmd(cmd->opcode);
65     ptr->SADDR = base_address;
66     if (!read_data) {
67         ptr->IPTX = cmd->data;
68     }
69     ptr->IPCMD = dram_make_cmd(cmd->opcode);
70 
71     if (dram_ip_cmd_done(ptr) < 0) {
72         return status_dram_cmd_err;
73     }
74 
75     if (read_data) {
76         cmd->data = ptr->IPRX;
77     }
78     return status_success;
79 }
80 
dram_default_config(DRAM_Type * ptr,dram_config_t * config)81 void dram_default_config(DRAM_Type *ptr, dram_config_t *config)
82 {
83     dram_axi_q_weight_t *q;
84     config->dqs = DRAM_DQS_FROM_PAD;
85     config->cmd_timeout = 0;
86     config->bus_timeout = 0x10;
87     q = &config->axi_q_weight[DRAM_AXI_Q_A];
88     q->enable = true;
89     q->qos = 4;
90     q->age = 2;
91     q->slave_hit = 0x5;
92     q->slave_hit_wo_rw = 0x3;
93 
94     q = &config->axi_q_weight[DRAM_AXI_Q_B];
95     q->enable = true;
96     q->qos = 4;
97     q->age = 2;
98     q->page_hit = 0x5;
99     q->slave_hit_wo_rw = 0x3;
100     q->bank_rotation = 0x6;
101 }
102 
dram_get_typical_sdram_config(DRAM_Type * ptr,dram_sdram_config_t * config)103 void dram_get_typical_sdram_config(DRAM_Type *ptr, dram_sdram_config_t *config)
104 {
105     config->col_addr_bits = DRAM_SDRAM_COLUMN_ADDR_9_BITS;
106     config->cas_latency = DRAM_SDRAM_CAS_LATENCY_3;
107     config->bank_num = DRAM_SDRAM_BANK_NUM_4;
108     config->prescaler = HPM_DRAM_DRV_DEFAULT_PRESCALER;
109     config->burst_len_in_byte = 8;
110     config->auto_refresh_count_in_one_burst = 1;
111     config->precharge_to_act_in_ns = 20;
112     config->act_to_rw_in_ns = 20;
113     config->refresh_recover_in_ns = 70;
114     config->write_recover_in_ns = 12;
115     config->cke_off_in_ns = 42;
116     config->act_to_precharge_in_ns = 42;
117 
118     config->self_refresh_recover_in_ns = 70;
119     config->refresh_to_refresh_in_ns = 60;
120     config->act_to_act_in_ns = 12;
121     config->idle_timeout_in_ns = 6;
122     config->cs_mux_pin = DRAM_IO_MUX_NOT_USED;
123 }
124 
dram_init(DRAM_Type * ptr,dram_config_t * config)125 void dram_init(DRAM_Type *ptr, dram_config_t *config)
126 {
127     uint32_t i;
128     dram_axi_q_weight_t *q;
129     for (i = 0; i < DRAM_BR_COUNT; i++) {
130         ptr->BR[i] = 0;
131     }
132 
133     dram_sw_reset(ptr);
134     dram_disable(ptr);
135     ptr->CTRL |= DRAM_CTRL_BTO_SET(config->bus_timeout)
136         | DRAM_CTRL_CTO_SET(config->cmd_timeout)
137         | DRAM_CTRL_DQS_SET(config->dqs);
138 
139     q = &config->axi_q_weight[DRAM_AXI_Q_A];
140     if (q->enable) {
141         ptr->BMW0 = DRAM_BMW0_QOS_SET(q->qos)
142             | DRAM_BMW0_AGE_SET(q->age)
143             | DRAM_BMW0_SH_SET(q->slave_hit)
144             | DRAM_BMW0_RWS_SET(q->slave_hit_wo_rw);
145     } else {
146         ptr->BMW0 = 0;
147     }
148 
149     q = &config->axi_q_weight[DRAM_AXI_Q_B];
150     if (q->enable) {
151         ptr->BMW1 = DRAM_BMW1_QOS_SET(q->qos)
152             | DRAM_BMW1_AGE_SET(q->age)
153             | DRAM_BMW1_PH_SET(q->page_hit)
154             | DRAM_BMW1_BR_SET(q->bank_rotation)
155             | DRAM_BMW1_RWS_SET(q->slave_hit_wo_rw);
156     } else {
157         ptr->BMW1 = 0;
158     }
159 
160     dram_enable(ptr);
161 }
162 
dram_convert_actual_size_to_memory_size(uint32_t size_in_kb)163 static uint8_t dram_convert_actual_size_to_memory_size(uint32_t size_in_kb)
164 {
165     uint8_t size = 0;
166     if (size_in_kb == 4) {
167         return 0;
168     }
169 
170     if (size_in_kb > 2 * 1 << 20) {
171         return 0x1F;
172     }
173 
174     size = 1;
175     size_in_kb >>= 3;
176     while (size_in_kb > 1) {
177         size_in_kb >>= 1;
178         size++;
179     }
180     return size;
181 }
182 
dram_convert_burst_len(uint8_t burst_len_in_byte)183 static uint8_t dram_convert_burst_len(uint8_t burst_len_in_byte)
184 {
185     if ((burst_len_in_byte == 0)
186             || (burst_len_in_byte > DRAM_SDRAM_MAX_BURST_LENGTH_IN_BYTE)) {
187         return DRAM_SDRAM_MAX_BURST_LENGTH_IN_BYTE + 1;
188     }
189 
190     switch (burst_len_in_byte) {
191     case 1:
192     case 2:
193     case 4:
194         return burst_len_in_byte >> 1;
195     case 8:
196         return (burst_len_in_byte - 1) >> 1;
197     default:
198         return DRAM_SDRAM_MAX_BURST_LENGTH_IN_BYTE + 1;
199     }
200 }
201 
ns2cycle(uint32_t freq_in_hz,uint32_t ns)202 static uint32_t ns2cycle(uint32_t freq_in_hz, uint32_t ns)
203 {
204     uint32_t ns_per_cycle;
205     ns_per_cycle = 1000000000 / freq_in_hz;
206     if (ns < ns_per_cycle) {
207         return 1;
208     }
209     return ns / ns_per_cycle;
210 }
211 
dram_config_sdram(DRAM_Type * ptr,uint32_t clk_in_hz,dram_sdram_config_t * config)212 hpm_stat_t dram_config_sdram(DRAM_Type *ptr, uint32_t clk_in_hz, dram_sdram_config_t *config)
213 {
214     hpm_stat_t err;
215     uint32_t prescaler;
216     uint32_t refresh_cycle;
217     uint32_t clk_in_khz = clk_in_hz / 1000;
218     dram_cmd_t cmd = {0};
219     uint8_t size = dram_convert_actual_size_to_memory_size(config->size_in_byte >> 10);
220     uint8_t burst_len = dram_convert_burst_len(config->burst_len_in_byte);
221 
222     prescaler = ((config->prescaler == 0) ? DRAM_PRESCALER_MAX : config->prescaler);
223     refresh_cycle = clk_in_khz * config->refresh_in_ms / config->refresh_count / (prescaler << 4);
224 
225     if ((prescaler == 0) || (prescaler > DRAM_PRESCALER_MAX)
226             || (refresh_cycle == 0) || (refresh_cycle > DRAM_PRESCALER_MAX)) {
227         return status_invalid_argument;
228     }
229 
230     if (prescaler == DRAM_PRESCALER_MAX) {
231         prescaler = 0;
232     }
233 
234     if (refresh_cycle == DRAM_PRESCALER_MAX) {
235         refresh_cycle = 0;
236     }
237 
238     ptr->BR[config->cs] = DRAM_BR_BASE_SET(config->base_address >> DRAM_BR_BASE_SHIFT)
239              | DRAM_BR_SIZE_SET(size) | DRAM_BR_VLD_MASK;
240 
241     ptr->SDRCTRL0 = DRAM_SDRCTRL0_PORTSZ_SET(config->port_size)
242                   | DRAM_SDRCTRL0_BURSTLEN_SET(burst_len)
243                   | DRAM_SDRCTRL0_COL_SET(config->col_addr_bits)
244                   | DRAM_SDRCTRL0_COL8_SET(config->col_addr_bits == DRAM_SDRAM_COLUMN_ADDR_8_BITS)
245                   | DRAM_SDRCTRL0_CAS_SET(config->cas_latency)
246                   | DRAM_SDRCTRL0_BANK2_SET(config->bank_num);
247 
248     ptr->SDRCTRL1 = DRAM_SDRCTRL1_PRE2ACT_SET(ns2cycle(clk_in_hz, config->precharge_to_act_in_ns))
249                   | DRAM_SDRCTRL1_ACT2RW_SET(ns2cycle(clk_in_hz, config->act_to_rw_in_ns))
250                   | DRAM_SDRCTRL1_RFRC_SET(ns2cycle(clk_in_hz, config->refresh_recover_in_ns))
251                   | DRAM_SDRCTRL1_WRC_SET(ns2cycle(clk_in_hz, config->write_recover_in_ns))
252                   | DRAM_SDRCTRL1_CKEOFF_SET(ns2cycle(clk_in_hz, config->cke_off_in_ns))
253                   | DRAM_SDRCTRL1_ACT2PRE_SET(ns2cycle(clk_in_hz, config->act_to_precharge_in_ns));
254 
255     ptr->SDRCTRL2 = DRAM_SDRCTRL2_SRRC_SET(ns2cycle(clk_in_hz, config->self_refresh_recover_in_ns))
256                   | DRAM_SDRCTRL2_REF2REF_SET(ns2cycle(clk_in_hz, config->refresh_to_refresh_in_ns))
257                   | DRAM_SDRCTRL2_ACT2ACT_SET(ns2cycle(clk_in_hz, config->act_to_act_in_ns))
258                   | DRAM_SDRCTRL2_ITO_SET(ns2cycle(clk_in_hz, config->idle_timeout_in_ns));
259 
260     ptr->SDRCTRL3 = DRAM_SDRCTRL3_PRESCALE_SET(prescaler)
261                   | DRAM_SDRCTRL3_RT_SET(refresh_cycle)
262                   | DRAM_SDRCTRL3_UT_SET(refresh_cycle)
263                   | DRAM_SDRCTRL3_REBL_SET(config->auto_refresh_count_in_one_burst - 1);
264     /*
265      *
266      * DATSZ[2:0]: Data size in byte
267      *     0b - 4
268      *     1b - 1
269      *     2b - 2
270      *     3b - 3
271      *   > 3b - 4
272      */
273     ptr->DATSZ = DRAM_DATSZ_DATSZ_SET((config->data_width_in_byte & (0x3UL)));
274     ptr->BYTEMSK = 0;
275 
276     cmd.opcode = DRAM_CMD_SDRAM_PRECHARGE_ALL;
277     cmd.data = 0;
278     err = dram_issue_ip_cmd(ptr, config->base_address, &cmd);
279     if (status_success != err) {
280         return err;
281     }
282 
283     cmd.opcode = DRAM_CMD_SDRAM_AUTO_REFRESH;
284     err = dram_issue_ip_cmd(ptr, config->base_address, &cmd);
285     if (status_success != err) {
286         return err;
287     }
288     err = dram_issue_ip_cmd(ptr, config->base_address, &cmd);
289     if (status_success != err) {
290         return err;
291     }
292 
293     /*
294      *
295      * DATSZ[2:0]: Data size in byte
296      *     0b - 4
297      *     1b - 1
298      *     2b - 2
299      *     3b - 3
300      *   > 3b - 4
301      */
302     ptr->DATSZ = DRAM_DATSZ_DATSZ_SET((config->data_width_in_byte & (0x3UL)));
303     ptr->BYTEMSK = 0;
304 
305     /*
306      * config delay cell
307      */
308     dram_config_delay_cell(ptr, config->delay_cell_value);
309 
310     cmd.opcode = DRAM_CMD_SDRAM_PRECHARGE_ALL;
311     cmd.data = 0;
312     err = dram_issue_ip_cmd(ptr, config->base_address, &cmd);
313     if (status_success != err) {
314         return err;
315     }
316 
317     cmd.opcode = DRAM_CMD_SDRAM_AUTO_REFRESH;
318     err = dram_issue_ip_cmd(ptr, config->base_address, &cmd);
319     if (status_success != err) {
320         return err;
321     }
322     err = dram_issue_ip_cmd(ptr, config->base_address, &cmd);
323     if (status_success != err) {
324         return err;
325     }
326 
327     cmd.opcode = DRAM_CMD_SDRAM_MODE_SET;
328     /* FIXME: the mode register layout definition better to be passed in? */
329     cmd.data = (uint32_t)(burst_len | config->cas_latency << 4);
330     err = dram_issue_ip_cmd(ptr, config->base_address, &cmd);
331     if (status_success != err) {
332         return err;
333     }
334     ptr->SDRCTRL3 |= DRAM_SDRCTRL3_REN_MASK;
335 
336     return status_success;
337 }
338 
339