hpm_ppi.c 11 KB

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