1 
2 /*
3  * Copyright (c) 2024 HPMicro
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  */
8 
9 /*---------------------------------------------------------------------
10  * Include
11  *---------------------------------------------------------------------
12  */
13 #include "hpm_ppi.h"
14 #include "hpm_clock_drv.h"
15 
ppi_ns2cycle(uint32_t ns)16 static uint32_t ppi_ns2cycle(uint32_t ns)
17 {
18     uint32_t ppi_freq = clock_get_frequency(clock_ppi0);
19     uint32_t max_cycle = PPI_CMD_CMD_CFG_CYCLE_NUM_MASK >> PPI_CMD_CMD_CFG_CYCLE_NUM_SHIFT;
20     uint32_t ns_per_cycle;
21     uint32_t cycle;
22 
23     ns_per_cycle = 1000000000 / ppi_freq;
24     cycle = ns / ns_per_cycle;
25     if (cycle > max_cycle) {
26         cycle = max_cycle;
27     }
28 
29     return cycle;
30 }
31 
32 /* API */
ppi_config_async_sram(PPI_Type * ppi,uint8_t cs_index,uint8_t cmd_start_index,ppi_async_sram_config_t * config)33 void ppi_config_async_sram(PPI_Type *ppi, uint8_t cs_index, uint8_t cmd_start_index, ppi_async_sram_config_t *config)
34 {
35     ppi_cs_pin_config_t cs_config;
36     ppi_cmd_config_t cmd_config;
37 
38     assert(!config->ad_mux_mode && (config->port_size != ppi_port_size_32bits));
39     assert(((config->base_address & 0xFFFFF) == 0) && (config->size_in_byte > 0));    /* Addr should be aligned by 1MB */
40 
41     /*
42      * Pin polarity Config
43      */
44     if (config->cs_valid_polarity) {
45         ppi_config_cs_pin_polarity(ppi, cs_index, ppi_cs_idle_pol_low);
46     } else {
47         ppi_config_cs_pin_polarity(ppi, cs_index, ppi_cs_idle_pol_high);
48     }
49 
50     if (config->ad_mux_mode) {
51         ppi_set_ctrl_pin_dir(ppi, config->adv_ctrl_pin, ppi_ctrl_pin_dir_output);
52         ppi_config_ctrl_pin_polarity(ppi, config->adv_ctrl_pin, ppi_ctrl_pol_low);
53     }
54     ppi_set_ctrl_pin_dir(ppi, config->rel_ctrl_pin, ppi_ctrl_pin_dir_output);
55     ppi_config_ctrl_pin_polarity(ppi, config->rel_ctrl_pin, ppi_ctrl_pol_low);
56     ppi_set_ctrl_pin_dir(ppi, config->wel_ctrl_pin, ppi_ctrl_pin_dir_output);
57     ppi_config_ctrl_pin_polarity(ppi, config->wel_ctrl_pin, ppi_ctrl_pol_low);
58 
59     /*
60      * Read Cmd
61      */
62     /* common */
63     cmd_config.cs_pin_value = config->cs_valid_polarity;
64     cmd_config.clk_output = false;
65     if (config->ad_mux_mode) {
66         cmd_config.byte_sel[0] = ppi_byte_sel_0_7_bits;
67         cmd_config.byte_sel[1] = ppi_byte_sel_8_15_bits;
68         cmd_config.byte_sel[2] = ppi_byte_sel_16_23_bits;
69         cmd_config.byte_sel[3] = ppi_byte_sel_24_31_bits;
70     } else {
71         if (config->port_size == ppi_port_size_8bits) {
72             cmd_config.ad_func_sel[0] = ppi_ad_func_data;
73             cmd_config.ad_pin_dir[0] = ppi_ad_pin_dir_input;
74             cmd_config.byte_sel[0] = ppi_byte_sel_0_7_bits;
75             for (uint8_t i = 1; i < 4; i++) {
76                 cmd_config.ad_func_sel[i] = ppi_ad_func_addr;
77                 cmd_config.ad_pin_dir[i] = ppi_ad_pin_dir_output;
78             }
79             cmd_config.byte_sel[1] = ppi_byte_sel_0_7_bits;
80             cmd_config.byte_sel[2] = ppi_byte_sel_8_15_bits;
81             cmd_config.byte_sel[3] = ppi_byte_sel_16_23_bits;
82         } else if (config->port_size == ppi_port_size_16bits) {
83             for (uint8_t i = 0; i < 2; i++) {
84                 cmd_config.ad_func_sel[i] = ppi_ad_func_data;
85                 cmd_config.ad_pin_dir[i] = ppi_ad_pin_dir_input;
86             }
87             cmd_config.byte_sel[0] = ppi_byte_sel_0_7_bits;
88             cmd_config.byte_sel[1] = ppi_byte_sel_8_15_bits;
89             for (uint8_t i = 2; i < 4; i++) {
90                 cmd_config.ad_func_sel[i] = ppi_ad_func_addr;
91                 cmd_config.ad_pin_dir[i] = ppi_ad_pin_dir_output;
92             }
93             cmd_config.byte_sel[2] = ppi_byte_sel_0_7_bits;
94             cmd_config.byte_sel[3] = ppi_byte_sel_8_15_bits;
95         } else {
96             ;    /* Not Support */
97         }
98     }
99     cmd_config.ctrl_pin_value[config->wel_ctrl_pin] = true;
100 
101     /* AS Stage */
102     cmd_config.cmd_cycle = ppi_ns2cycle(config->as_in_ns);
103     if (config->ad_mux_mode) {
104         for (uint8_t i = 0; i < 4; i++) {
105             cmd_config.ad_func_sel[i] = ppi_ad_func_addr;
106             cmd_config.ad_pin_dir[i] = ppi_ad_pin_dir_output;
107         }
108         cmd_config.ctrl_pin_value[config->adv_ctrl_pin] = config->addr_valid_polarity;
109     }
110     cmd_config.ctrl_pin_value[config->rel_ctrl_pin] = true;
111     ppi_config_cmd(ppi, cmd_start_index, &cmd_config);
112 
113     /* AH Stage */
114     cmd_config.cmd_cycle = ppi_ns2cycle(config->ah_in_ns);
115     if (config->ad_mux_mode) {
116         for (uint8_t i = 0; i < 4; i++) {
117             cmd_config.ad_func_sel[i] = ppi_ad_func_addr;
118             cmd_config.ad_pin_dir[i] = ppi_ad_pin_dir_output;
119         }
120         cmd_config.ctrl_pin_value[config->adv_ctrl_pin] = !config->addr_valid_polarity;
121     }
122     cmd_config.ctrl_pin_value[config->rel_ctrl_pin] = true;
123     ppi_config_cmd(ppi, cmd_start_index + 1, &cmd_config);
124 
125     /* REL Stage */
126     cmd_config.cmd_cycle = ppi_ns2cycle(config->rel_in_ns);
127     if (config->ad_mux_mode) {
128         for (uint8_t i = 0; i < 4; i++) {
129             cmd_config.ad_func_sel[i] = ppi_ad_func_data;
130             cmd_config.ad_pin_dir[i] = ppi_ad_pin_dir_input;
131         }
132         cmd_config.ctrl_pin_value[config->adv_ctrl_pin] = !config->addr_valid_polarity;
133     }
134     cmd_config.ctrl_pin_value[config->rel_ctrl_pin] = false;
135     ppi_config_cmd(ppi, cmd_start_index + 2, &cmd_config);
136 
137     /* REH Stage */
138     cmd_config.cmd_cycle = ppi_ns2cycle(config->reh_in_ns);
139     if (config->ad_mux_mode) {
140         for (uint8_t i = 0; i < 4; i++) {
141             cmd_config.ad_func_sel[i] = ppi_ad_func_data;
142             cmd_config.ad_pin_dir[i] = ppi_ad_pin_dir_input;
143         }
144         cmd_config.ctrl_pin_value[config->adv_ctrl_pin] = !config->addr_valid_polarity;
145     }
146     cmd_config.ctrl_pin_value[config->rel_ctrl_pin] = true;
147     ppi_config_cmd(ppi, cmd_start_index + 3, &cmd_config);
148 
149     /*
150      * Write Cmd
151      */
152     /* common */
153     cmd_config.cs_pin_value = config->cs_valid_polarity;
154     cmd_config.clk_output = false;
155     if (config->ad_mux_mode) {
156         cmd_config.byte_sel[0] = ppi_byte_sel_0_7_bits;
157         cmd_config.byte_sel[1] = ppi_byte_sel_8_15_bits;
158         cmd_config.byte_sel[2] = ppi_byte_sel_16_23_bits;
159         cmd_config.byte_sel[3] = ppi_byte_sel_24_31_bits;
160     } else {
161         if (config->port_size == ppi_port_size_8bits) {
162             cmd_config.ad_func_sel[0] = ppi_ad_func_data;
163             cmd_config.ad_pin_dir[0] = ppi_ad_pin_dir_output;
164             cmd_config.byte_sel[0] = ppi_byte_sel_0_7_bits;
165             for (uint8_t i = 1; i < 4; i++) {
166                 cmd_config.ad_func_sel[i] = ppi_ad_func_addr;
167                 cmd_config.ad_pin_dir[i] = ppi_ad_pin_dir_output;
168             }
169             cmd_config.byte_sel[1] = ppi_byte_sel_0_7_bits;
170             cmd_config.byte_sel[2] = ppi_byte_sel_8_15_bits;
171             cmd_config.byte_sel[3] = ppi_byte_sel_16_23_bits;
172         } else if (config->port_size == ppi_port_size_16bits) {
173             for (uint8_t i = 0; i < 2; i++) {
174                 cmd_config.ad_func_sel[i] = ppi_ad_func_data;
175                 cmd_config.ad_pin_dir[i] = ppi_ad_pin_dir_output;
176             }
177             cmd_config.byte_sel[0] = ppi_byte_sel_0_7_bits;
178             cmd_config.byte_sel[1] = ppi_byte_sel_8_15_bits;
179             for (uint8_t i = 2; i < 4; i++) {
180                 cmd_config.ad_func_sel[i] = ppi_ad_func_addr;
181                 cmd_config.ad_pin_dir[i] = ppi_ad_pin_dir_output;
182             }
183             cmd_config.byte_sel[2] = ppi_byte_sel_0_7_bits;
184             cmd_config.byte_sel[3] = ppi_byte_sel_8_15_bits;
185         } else {
186             ;    /* Not Support */
187         }
188     }
189     cmd_config.ctrl_pin_value[config->rel_ctrl_pin] = true;
190 
191     /* AS Stage */
192     cmd_config.cmd_cycle = ppi_ns2cycle(config->as_in_ns);
193     if (config->ad_mux_mode) {
194         for (uint8_t i = 0; i < 4; i++) {
195             cmd_config.ad_func_sel[i] = ppi_ad_func_addr;
196             cmd_config.ad_pin_dir[i] = ppi_ad_pin_dir_output;
197         }
198         cmd_config.ctrl_pin_value[config->adv_ctrl_pin] = config->addr_valid_polarity;
199     }
200     cmd_config.ctrl_pin_value[config->wel_ctrl_pin] = true;
201     ppi_config_cmd(ppi, cmd_start_index + 4, &cmd_config);
202 
203     /* AH Stage */
204     cmd_config.cmd_cycle = ppi_ns2cycle(config->ah_in_ns);
205     if (config->ad_mux_mode) {
206         for (uint8_t i = 0; i < 4; i++) {
207             cmd_config.ad_func_sel[i] = ppi_ad_func_addr;
208             cmd_config.ad_pin_dir[i] = ppi_ad_pin_dir_output;
209         }
210         cmd_config.ctrl_pin_value[config->adv_ctrl_pin] = !config->addr_valid_polarity;
211     }
212     cmd_config.ctrl_pin_value[config->wel_ctrl_pin] = true;
213     ppi_config_cmd(ppi, cmd_start_index + 5, &cmd_config);
214 
215     /* WEL Stage */
216     cmd_config.cmd_cycle = ppi_ns2cycle(config->wel_in_ns);
217     if (config->ad_mux_mode) {
218         for (uint8_t i = 0; i < 4; i++) {
219             cmd_config.ad_func_sel[i] = ppi_ad_func_data;
220             cmd_config.ad_pin_dir[i] = ppi_ad_pin_dir_output;
221         }
222         cmd_config.ctrl_pin_value[config->adv_ctrl_pin] = !config->addr_valid_polarity;
223     }
224     cmd_config.ctrl_pin_value[config->wel_ctrl_pin] = false;
225     ppi_config_cmd(ppi, cmd_start_index + 6, &cmd_config);
226 
227     /* WEH Stage */
228     cmd_config.cmd_cycle = ppi_ns2cycle(config->weh_in_ns);
229     if (config->ad_mux_mode) {
230         for (uint8_t i = 0; i < 4; i++) {
231             cmd_config.ad_func_sel[i] = ppi_ad_func_data;
232             cmd_config.ad_pin_dir[i] = ppi_ad_pin_dir_output;
233         }
234         cmd_config.ctrl_pin_value[config->adv_ctrl_pin] = !config->addr_valid_polarity;
235     }
236     cmd_config.ctrl_pin_value[config->wel_ctrl_pin] = true;
237     ppi_config_cmd(ppi, cmd_start_index + 7, &cmd_config);
238 
239     /*
240      * CS Config
241      */
242     cs_config.addr_start_high_12bits = (config->base_address & 0xFFF00000u) >> 20u;
243     cs_config.addr_end_high_12bits = ((config->base_address + (config->size_in_byte - 1u)) & 0xFFF00000u) >> 20u;
244     cs_config.port_size = config->port_size;
245     cs_config.addr_mask = 0xFFFFu;
246     cs_config.sync_clk_en = false;
247     cs_config.sync_clk_sel = 0;
248     cs_config.interval_cycle = 2;
249     cs_config.rcmd_start0 = cmd_start_index;
250     cs_config.rcmd_end0 = cmd_start_index + 3;
251     cs_config.rcmd_start1 = cmd_start_index;
252     cs_config.rcmd_end1 = cmd_start_index + 3;
253     cs_config.wcmd_start0 = cmd_start_index + 4;
254     cs_config.wcmd_end0 = cmd_start_index + 7;
255     cs_config.wcmd_start1 = cmd_start_index + 4;
256     cs_config.wcmd_end1 = cmd_start_index + 7;
257 #if defined(HPM_IP_FEATURE_PPI_DM_POLARITY_EACH_CS) && HPM_IP_FEATURE_PPI_DM_POLARITY_EACH_CS
258     if (config->dm_valid_polarity) {
259         cs_config.dm_polarity = ppi_dm_valid_pol_high;
260     } else {
261         cs_config.dm_polarity = ppi_dm_valid_pol_low;
262     }
263 #else
264     if (config->dm_valid_polarity) {
265         ppi_config_dm_pin_polarity(ppi, cs_index, ppi_dm_valid_pol_high);
266     } else {
267         ppi_config_dm_pin_polarity(ppi, cs_index, ppi_dm_valid_pol_low);
268     }
269 #endif
270     ppi_config_cs_pin(ppi, cs_index, &cs_config);
271 }
272