sdio_slave_ll.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. // Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. /*******************************************************************************
  14. * NOTICE
  15. * The hal is not public api, don't use in application code.
  16. * See readme.md in soc/include/hal/readme.md
  17. ******************************************************************************/
  18. // The LL layer for ESP32 SDIO slave register operations
  19. // It's strange but `tx_*` regs for host->slave transfers while `rx_*` regs for slave->host transfers
  20. // To reduce ambiguity, we call (host->slave, tx) transfers receiving and (slave->host, rx) transfers receiving
  21. #pragma once
  22. #include "hal/sdio_slave_hal.h"
  23. #include "soc/slc_struct.h"
  24. #include "soc/slc_reg.h"
  25. #include "soc/host_struct.h"
  26. #include "soc/host_reg.h"
  27. #include "soc/hinf_struct.h"
  28. #include "soc/lldesc.h"
  29. /// Get address of the only SLC registers for ESP32
  30. #define sdio_slave_ll_get_slc(ID) (&SLC)
  31. /// Get address of the only HOST registers for ESP32
  32. #define sdio_slave_ll_get_host(ID) (&HOST)
  33. /// Get address of the only HINF registers for ESP32
  34. #define sdio_slave_ll_get_hinf(ID) (&HINF)
  35. /// Mask of general purpose interrupts sending from the host.
  36. typedef enum {
  37. SDIO_SLAVE_LL_SLVINT_0 = BIT(0), ///< General purpose interrupt bit 0.
  38. SDIO_SLAVE_LL_SLVINT_1 = BIT(1),
  39. SDIO_SLAVE_LL_SLVINT_2 = BIT(2),
  40. SDIO_SLAVE_LL_SLVINT_3 = BIT(3),
  41. SDIO_SLAVE_LL_SLVINT_4 = BIT(4),
  42. SDIO_SLAVE_LL_SLVINT_5 = BIT(5),
  43. SDIO_SLAVE_LL_SLVINT_6 = BIT(6),
  44. SDIO_SLAVE_LL_SLVINT_7 = BIT(7),
  45. } sdio_slave_ll_slvint_t;
  46. /**
  47. * Initialize the hardware.
  48. *
  49. * @param slc Address of the SLC registers
  50. */
  51. static inline void sdio_slave_ll_init(slc_dev_t *slc)
  52. {
  53. slc->slc0_int_ena.val = 0;
  54. slc->conf0.slc0_rx_auto_wrback = 1;
  55. slc->conf0.slc0_token_auto_clr = 0;
  56. slc->conf0.slc0_rx_loop_test = 0;
  57. slc->conf0.slc0_tx_loop_test = 0;
  58. slc->conf1.slc0_rx_stitch_en = 0;
  59. slc->conf1.slc0_tx_stitch_en = 0;
  60. slc->conf1.slc0_len_auto_clr = 0;
  61. slc->rx_dscr_conf.slc0_token_no_replace = 1;
  62. }
  63. /**
  64. * Set the timing for the communication
  65. *
  66. * @param host Address of the host registers
  67. * @param timing Timing configuration to set
  68. */
  69. static inline void sdio_slave_ll_set_timing(host_dev_t *host, sdio_slave_timing_t timing)
  70. {
  71. switch(timing) {
  72. case SDIO_SLAVE_TIMING_PSEND_PSAMPLE:
  73. host->conf.frc_sdio20 = 0x1f;
  74. host->conf.frc_sdio11 = 0;
  75. host->conf.frc_pos_samp = 0x1f;
  76. host->conf.frc_neg_samp = 0;
  77. break;
  78. case SDIO_SLAVE_TIMING_PSEND_NSAMPLE:
  79. host->conf.frc_sdio20 = 0x1f;
  80. host->conf.frc_sdio11 = 0;
  81. host->conf.frc_pos_samp = 0;
  82. host->conf.frc_neg_samp = 0x1f;
  83. break;
  84. case SDIO_SLAVE_TIMING_NSEND_PSAMPLE:
  85. host->conf.frc_sdio20 = 0;
  86. host->conf.frc_sdio11 = 0x1f;
  87. host->conf.frc_pos_samp = 0x1f;
  88. host->conf.frc_neg_samp = 0;
  89. break;
  90. case SDIO_SLAVE_TIMING_NSEND_NSAMPLE:
  91. host->conf.frc_sdio20 = 0;
  92. host->conf.frc_sdio11 = 0x1f;
  93. host->conf.frc_pos_samp = 0;
  94. host->conf.frc_neg_samp = 0x1f;
  95. break;
  96. }
  97. }
  98. /**
  99. * Set the HS supported bit to be read by the host.
  100. *
  101. * @param hinf Address of the hinf registers
  102. * @param hs true if supported, otherwise false.
  103. */
  104. static inline void sdio_slave_ll_enable_hs(hinf_dev_t *hinf, bool hs)
  105. {
  106. if (hs) {
  107. hinf->cfg_data1.sdio_ver = 0x232;
  108. hinf->cfg_data1.highspeed_enable = 1;
  109. }
  110. }
  111. /**
  112. * Set the IO Ready bit to be read by the host.
  113. *
  114. * @param hinf Address of the hinf registers
  115. * @param ready true if ready, otherwise false.
  116. */
  117. static inline void sdio_slave_ll_set_ioready(hinf_dev_t *hinf, bool ready)
  118. {
  119. hinf->cfg_data1.sdio_ioready1 = (ready ? 1 : 0); //set IO ready to 1 to stop host from using
  120. }
  121. /*---------------------------------------------------------------------------
  122. * Send
  123. *--------------------------------------------------------------------------*/
  124. /**
  125. * Reset the sending DMA.
  126. *
  127. * @param slc Address of the SLC registers
  128. */
  129. static inline void sdio_slave_ll_send_reset(slc_dev_t *slc)
  130. {
  131. //reset to flush previous packets
  132. slc->conf0.slc0_rx_rst = 1;
  133. slc->conf0.slc0_rx_rst = 0;
  134. }
  135. /**
  136. * Start the sending DMA with the given descriptor.
  137. *
  138. * @param slc Address of the SLC registers
  139. * @param desc Descriptor to send
  140. */
  141. static inline void sdio_slave_ll_send_start(slc_dev_t *slc, const lldesc_t *desc)
  142. {
  143. slc->slc0_rx_link.addr = (uint32_t)desc;
  144. slc->slc0_rx_link.start = 1;
  145. }
  146. /**
  147. * Write the PKT_LEN register to be written by the host to a certain value.
  148. *
  149. * @param slc Address of the SLC registers
  150. * @param len Length to write
  151. */
  152. static inline void sdio_slave_ll_send_write_len(slc_dev_t *slc, uint32_t len)
  153. {
  154. slc->slc0_len_conf.val = FIELD_TO_VALUE2(SLC_SLC0_LEN_WDATA, len) | FIELD_TO_VALUE2(SLC_SLC0_LEN_WR, 1);
  155. }
  156. /**
  157. * Read the value of PKT_LEN register. The register may keep the same until read
  158. * by the host.
  159. *
  160. * @param host Address of the host registers
  161. * @return The value of PKT_LEN register.
  162. */
  163. static inline uint32_t sdio_slave_ll_send_read_len(host_dev_t *host)
  164. {
  165. return host->pkt_len.reg_slc0_len;
  166. }
  167. /**
  168. * Enable the rx_done interrupt. (sending)
  169. *
  170. * @param slc Address of the SLC registers
  171. * @param ena true if enable, otherwise false.
  172. */
  173. static inline void sdio_slave_ll_send_part_done_intr_ena(slc_dev_t *slc, bool ena)
  174. {
  175. slc->slc0_int_ena.rx_done = (ena ? 1 : 0);
  176. }
  177. /**
  178. * Clear the rx_done interrupt. (sending)
  179. *
  180. * @param slc Address of the SLC registers
  181. */
  182. static inline void sdio_slave_ll_send_part_done_clear(slc_dev_t *slc)
  183. {
  184. slc->slc0_int_clr.rx_done = 1;
  185. }
  186. /**
  187. * Check whether the hardware is ready for the SW to use rx_done to invoke
  188. * the ISR.
  189. *
  190. * @param slc Address of the SLC registers
  191. * @return true if ready, otherwise false.
  192. */
  193. static inline bool sdio_slave_ll_send_invoker_ready(slc_dev_t *slc)
  194. {
  195. return slc->slc0_int_raw.rx_done;
  196. }
  197. /**
  198. * Stop the sending DMA.
  199. *
  200. * @param slc Address of the SLC registers
  201. */
  202. static inline void sdio_slave_ll_send_stop(slc_dev_t *slc)
  203. {
  204. slc->slc0_rx_link.stop = 1;
  205. }
  206. /**
  207. * Enable the sending interrupt (rx_eof).
  208. *
  209. * @param slc Address of the SLC registers
  210. * @param ena true to enable, false to disable
  211. */
  212. static inline void sdio_slave_ll_send_intr_ena(slc_dev_t *slc, bool ena)
  213. {
  214. slc->slc0_int_ena.rx_eof = (ena? 1: 0);
  215. }
  216. /**
  217. * Clear the sending interrupt (rx_eof).
  218. *
  219. * @param slc Address of the SLC registers
  220. */
  221. static inline void sdio_slave_ll_send_intr_clr(slc_dev_t *slc)
  222. {
  223. slc->slc0_int_clr.rx_eof = 1;
  224. }
  225. /**
  226. * Check whether the sending is done.
  227. *
  228. * @param slc Address of the SLC registers
  229. * @return true if done, otherwise false
  230. */
  231. static inline bool sdio_slave_ll_send_done(slc_dev_t *slc)
  232. {
  233. return slc->slc0_int_st.rx_eof != 0;
  234. }
  235. /**
  236. * Clear the host interrupt indicating the slave having packet to be read.
  237. *
  238. * @param host Address of the host registers
  239. */
  240. static inline void sdio_slave_ll_send_hostint_clr(host_dev_t *host)
  241. {
  242. host->slc0_int_clr.rx_new_packet = 1;
  243. }
  244. /*---------------------------------------------------------------------------
  245. * Receive
  246. *--------------------------------------------------------------------------*/
  247. /**
  248. * Enable the receiving interrupt.
  249. *
  250. * @param slc Address of the SLC registers
  251. * @param ena
  252. */
  253. static inline void sdio_slave_ll_recv_intr_ena(slc_dev_t *slc, bool ena)
  254. {
  255. slc->slc0_int_ena.tx_done = (ena ? 1 : 0);
  256. }
  257. /**
  258. * Start receiving DMA with the given descriptor.
  259. *
  260. * @param slc Address of the SLC registers
  261. * @param desc Descriptor of the receiving buffer.
  262. */
  263. static inline void sdio_slave_ll_recv_start(slc_dev_t *slc, lldesc_t *desc)
  264. {
  265. slc->slc0_tx_link.addr = (uint32_t)desc;
  266. slc->slc0_tx_link.start = 1;
  267. }
  268. /**
  269. * Increase the receiving buffer counter by 1.
  270. *
  271. * @param slc Address of the SLC registers
  272. */
  273. static inline void sdio_slave_ll_recv_size_inc(slc_dev_t *slc)
  274. {
  275. // fields wdata and inc_more should be written by the same instruction.
  276. slc->slc0_token1.val = FIELD_TO_VALUE2(SLC_SLC0_TOKEN1_WDATA, 1) | FIELD_TO_VALUE2(SLC_SLC0_TOKEN1_INC_MORE, 1);
  277. }
  278. /**
  279. * Reset the receiving buffer.
  280. *
  281. * @param slc Address of the SLC registers
  282. */
  283. static inline void sdio_slave_ll_recv_size_reset(slc_dev_t *slc)
  284. {
  285. slc->slc0_token1.val = FIELD_TO_VALUE2(SLC_SLC0_TOKEN1_WDATA, 0) | FIELD_TO_VALUE2(SLC_SLC0_TOKEN1_WR, 1);
  286. }
  287. /**
  288. * Check whether there is a receiving finished event.
  289. *
  290. * @param slc Address of the SLC registers
  291. * @return
  292. */
  293. static inline bool sdio_slave_ll_recv_done(slc_dev_t *slc)
  294. {
  295. return slc->slc0_int_raw.tx_done != 0;
  296. }
  297. /**
  298. * Clear the receiving finished interrupt.
  299. *
  300. * @param slc Address of the SLC registers
  301. */
  302. static inline void sdio_slave_ll_recv_done_clear(slc_dev_t *slc)
  303. {
  304. slc->slc0_int_clr.tx_done = 1;
  305. }
  306. /**
  307. * Restart the DMA. Call after you modified the next pointer of the tail descriptor to the appended
  308. * descriptor.
  309. *
  310. * @param slc Address of the SLC registers
  311. */
  312. static inline void sdio_slave_ll_recv_restart(slc_dev_t *slc)
  313. {
  314. slc->slc0_tx_link.restart = 1;
  315. }
  316. /**
  317. * Reset the receiving DMA.
  318. *
  319. * @param slc Address of the SLC registers
  320. */
  321. static inline void sdio_slave_ll_recv_reset(slc_dev_t *slc)
  322. {
  323. slc->conf0.slc0_tx_rst = 1;
  324. slc->conf0.slc0_tx_rst = 0;
  325. }
  326. /**
  327. * Stop the receiving DMA.
  328. *
  329. * @param slc Address of the SLC registers
  330. */
  331. static inline void sdio_slave_ll_recv_stop(slc_dev_t *slc)
  332. {
  333. slc->slc0_tx_link.stop = 1;
  334. }
  335. /*---------------------------------------------------------------------------
  336. * Host
  337. *--------------------------------------------------------------------------*/
  338. /**
  339. * Get the address of the shared general purpose register. Internal.
  340. *
  341. * @param host Address of the host registers
  342. * @param pos Position of the register, 0-63 except 24-27.
  343. * @return address of the register.
  344. */
  345. static inline intptr_t sdio_slave_ll_host_get_w_reg(host_dev_t* host, int pos)
  346. {
  347. return (intptr_t )&(host->conf_w0) + pos + (pos>23?4:0) + (pos>31?12:0);
  348. }
  349. /**
  350. * Get the value of the shared general purpose register.
  351. *
  352. * @param host Address of the host registers
  353. * @param pos Position of the register, 0-63, except 24-27.
  354. * @return value of the register.
  355. */
  356. static inline uint8_t sdio_slave_ll_host_get_reg(host_dev_t *host, int pos)
  357. {
  358. return *(uint8_t*)sdio_slave_ll_host_get_w_reg(host, pos);
  359. }
  360. /**
  361. * Set the value of the shared general purpose register.
  362. *
  363. * @param host Address of the host registers
  364. * @param pos Position of the register, 0-63, except 24-27.
  365. * @param reg Value to set.
  366. */
  367. static inline void sdio_slave_ll_host_set_reg(host_dev_t* host, int pos, uint8_t reg)
  368. {
  369. uint32_t* addr = (uint32_t*)(sdio_slave_ll_host_get_w_reg(host, pos) & (~3));
  370. uint32_t shift = (pos % 4) * 8;
  371. *addr &= ~(0xff << shift);
  372. *addr |= ((uint32_t)reg << shift);
  373. }
  374. /**
  375. * Get the interrupt enable bits for the host.
  376. *
  377. * @param host Address of the host registers
  378. * @return Enabled interrupts
  379. */
  380. static inline sdio_slave_hostint_t sdio_slave_ll_host_get_intena(host_dev_t* host)
  381. {
  382. return host->slc0_func1_int_ena.val;
  383. }
  384. /**
  385. * Set the interrupt enable bits for the host.
  386. *
  387. * @param host Address of the host registers
  388. * @param mask Mask of interrupts to enable
  389. */
  390. static inline void sdio_slave_ll_host_set_intena(host_dev_t *host, const sdio_slave_hostint_t *mask)
  391. {
  392. host->slc0_func1_int_ena.val = (*mask);
  393. }
  394. /**
  395. * Clear the interrupt bits for the host.
  396. * @param host Address of the host registers
  397. * @param mask Mask of interrupts to clear.
  398. */
  399. static inline void sdio_slave_ll_host_intr_clear(host_dev_t* host, const sdio_slave_hostint_t *mask)
  400. {
  401. host->slc0_int_clr.val = (*mask);
  402. }
  403. /**
  404. * Send general purpose interrupts to the host.
  405. * @param slc Address of the SLC registers
  406. * @param mask Mask of interrupts to seend to host
  407. */
  408. static inline void sdio_slave_ll_host_send_int(slc_dev_t *slc, const sdio_slave_hostint_t *mask)
  409. {
  410. //use registers in SLC to trigger, rather than write HOST registers directly
  411. //other interrupts than tohost interrupts are not supported yet
  412. slc->intvec_tohost.slc0_intvec = (*mask);
  413. }
  414. /**
  415. * Enable some of the slave interrups (send from host)
  416. *
  417. * @param slc Address of the SLC registers
  418. * @param mask Mask of interrupts to enable, all those set to 0 will be disabled.
  419. */
  420. static inline void sdio_slave_ll_slvint_set_ena(slc_dev_t *slc, const sdio_slave_ll_slvint_t *mask)
  421. {
  422. //other interrupts are not enabled
  423. slc->slc0_int_ena.val = (slc->slc0_int_ena.val & (~0xff)) | ((*mask) & 0xff);
  424. }
  425. /**
  426. * Fetch the slave interrupts (send from host) and clear them.
  427. *
  428. * @param slc Address of the SLC registers
  429. * @param out_slv_int Output of the slave interrupts fetched and cleared.
  430. */
  431. static inline void sdio_slave_ll_slvint_fetch_clear(slc_dev_t *slc, sdio_slave_ll_slvint_t *out_slv_int)
  432. {
  433. sdio_slave_ll_slvint_t slv_int = slc->slc0_int_st.val & 0xff;
  434. *out_slv_int = slv_int;
  435. slc->slc0_int_clr.val = slv_int;
  436. }