fsl_mipi_csi2rx.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /*
  2. * Copyright 2017, 2019-2020 NXP
  3. * All rights reserved.
  4. *
  5. *
  6. * SPDX-License-Identifier: BSD-3-Clause
  7. */
  8. #include "fsl_mipi_csi2rx.h"
  9. /*
  10. * The MIPI CSI2 peripheral can not work independently, some other control and
  11. * status registers must be used together. There are two integration methods
  12. * with these registers.
  13. *
  14. * 1. The registers are collected in one dedicated module: CSR.
  15. * 2. The registers are scattered in multiple modules.
  16. *
  17. */
  18. /*******************************************************************************
  19. * Definitions
  20. ******************************************************************************/
  21. /* Component ID definition, used by tools. */
  22. #ifndef FSL_COMPONENT_ID
  23. #define FSL_COMPONENT_ID "platform.drivers.mipi_csi2rx"
  24. #endif
  25. #if (defined(FSL_FEATURE_CSI2RX_CSR_OFFSET) && FSL_FEATURE_CSI2RX_CSR_OFFSET)
  26. #define CSI2RX_GET_CSR(csi_base) (MIPI_CSI_CSR_Type *)((uint32_t)(csi_base) - (uint32_t)FSL_FEATURE_CSI2RX_CSR_OFFSET)
  27. #define MIPI_CSI2RX_HAS_CSR 1
  28. #else
  29. #define MIPI_CSI2RX_HAS_CSR 0
  30. #include "fsl_soc_mipi_csi2rx.h"
  31. #endif
  32. #if MIPI_CSI2RX_HAS_CSR
  33. /* Macro Map */
  34. #ifndef MIPI_CSI_CSR_CONTROLLER_CLOCK_RESET_CONTROL_CTL_CLK_OFF_MASK
  35. #define MIPI_CSI_CSR_CONTROLLER_CLOCK_RESET_CONTROL_CTL_CLK_OFF_MASK \
  36. MIPI_CSI_CSR_CONTROLLER_CLOCK_RESET_CONTROL_CONTROLLER_CLOCK_RESET_CONTROL(2U)
  37. #define MIPI_CSI_CSR_CONTROLLER_CLOCK_RESET_CONTROL_SW_RESET_MASK \
  38. MIPI_CSI_CSR_CONTROLLER_CLOCK_RESET_CONTROL_CONTROLLER_CLOCK_RESET_CONTROL(1U)
  39. #endif
  40. #ifndef MIPI_CSI_CSR_PHY_CTRL_CONTI_CLK_MODE_MASK
  41. #define MIPI_CSI_CSR_PHY_CTRL_CONTI_CLK_MODE_MASK MIPI_CSI_CSR_PHY_CTRL_CONT_CLK_MODE_MASK
  42. #endif
  43. #ifndef MIPI_CSI_CSR_PHY_CTRL_PRG_RXHS_SETTLE
  44. #define MIPI_CSI_CSR_PHY_CTRL_PRG_RXHS_SETTLE(x) MIPI_CSI_CSR_PHY_CTRL_S_PRG_RXHS_SETTLE(x)
  45. #endif
  46. #endif
  47. /*******************************************************************************
  48. * Prototypes
  49. ******************************************************************************/
  50. /*!
  51. * @brief Returns an instance number given a base address.
  52. *
  53. * If an invalid base address is passed, debug builds will assert. Release builds will just return
  54. * instance number 0.
  55. *
  56. * @param base The CSI2RX peripheral base address.
  57. * @return CSI2RX instance number starting from 0.
  58. */
  59. uint32_t CSI2RX_GetInstance(MIPI_CSI2RX_Type *base);
  60. #if MIPI_CSI2RX_HAS_CSR
  61. /*!
  62. * @brief Perform CSI2RX resource reset in system level.
  63. *
  64. * @param base The CSI2RX peripheral base address.
  65. * @param reset Pass in true to set to reset state, false to release reset.
  66. */
  67. static void MIPI_CSI2RX_SoftwareReset(MIPI_CSI2RX_Type *base, bool reset);
  68. /*!
  69. * @brief Initialize the CSI2RX interface.
  70. *
  71. * @param base The CSI2RX peripheral base address.
  72. * @param tHsSettle_EscClk t-HS_SETTLE in esc clock period.
  73. */
  74. static void MIPI_CSI2RX_InitInterface(MIPI_CSI2RX_Type *base, uint8_t tHsSettle_EscClk);
  75. /*!
  76. * @brief Deinitialize the CSI2RX interface.
  77. *
  78. * @param base The CSI2RX peripheral base address.
  79. */
  80. static void MIPI_CSI2RX_DeinitInterface(MIPI_CSI2RX_Type *base);
  81. #endif
  82. /*******************************************************************************
  83. * Variables
  84. ******************************************************************************/
  85. /*! @brief Array to map MIPI CSI2RX instance number to base address. */
  86. static const uint32_t s_csi2rxBaseAddrs[] = MIPI_CSI2RX_BASE_ADDRS;
  87. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  88. /*! @brief Pointers to MPI CSI2RX clocks for each instance. */
  89. static const clock_ip_name_t s_csi2rxClocks[] = MIPI_CSI2RX_CLOCKS;
  90. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  91. /*******************************************************************************
  92. * Code
  93. ******************************************************************************/
  94. #if MIPI_CSI2RX_HAS_CSR
  95. static void MIPI_CSI2RX_SoftwareReset(MIPI_CSI2RX_Type *base, bool reset)
  96. {
  97. MIPI_CSI_CSR_Type *csr = CSI2RX_GET_CSR(base);
  98. if (reset)
  99. {
  100. csr->CONTROLLER_CLOCK_RESET_CONTROL = MIPI_CSI_CSR_CONTROLLER_CLOCK_RESET_CONTROL_CTL_CLK_OFF_MASK;
  101. }
  102. else
  103. {
  104. csr->CONTROLLER_CLOCK_RESET_CONTROL = MIPI_CSI_CSR_CONTROLLER_CLOCK_RESET_CONTROL_CTL_CLK_OFF_MASK;
  105. csr->CONTROLLER_CLOCK_RESET_CONTROL = MIPI_CSI_CSR_CONTROLLER_CLOCK_RESET_CONTROL_SW_RESET_MASK |
  106. MIPI_CSI_CSR_CONTROLLER_CLOCK_RESET_CONTROL_CTL_CLK_OFF_MASK;
  107. }
  108. }
  109. static void MIPI_CSI2RX_InitInterface(MIPI_CSI2RX_Type *base, uint8_t tHsSettle_EscClk)
  110. {
  111. MIPI_CSI_CSR_Type *csr = CSI2RX_GET_CSR(base);
  112. /* Pixel link control */
  113. csr->PLM_CTRL = 0;
  114. /* Configure the PHY. */
  115. csr->PHY_CTRL = MIPI_CSI_CSR_PHY_CTRL_RX_ENABLE_MASK | /* Enable RX. */
  116. MIPI_CSI_CSR_PHY_CTRL_AUTO_PD_EN_MASK | /* Auto power down unused lanes. */
  117. MIPI_CSI_CSR_PHY_CTRL_PD_MASK | MIPI_CSI_CSR_PHY_CTRL_DDRCLK_EN_MASK | /* Enable the DDR clock. */
  118. MIPI_CSI_CSR_PHY_CTRL_CONTI_CLK_MODE_MASK | /* Continue clock. */
  119. MIPI_CSI_CSR_PHY_CTRL_RTERM_SEL_MASK | /* LPRX voltage level enable HS termination */
  120. MIPI_CSI_CSR_PHY_CTRL_PRG_RXHS_SETTLE(tHsSettle_EscClk - 1UL); /* T(HS-SETTLE) */
  121. /* Don't support interlace currently. */
  122. csr->VC_INTERLACED = 0U;
  123. /* Don't mask any data type */
  124. #if defined(MIPI_CSI_CSR_DATA_TYPE_DISABLE_BF_DATA_TYPE_DISABLE_MASK)
  125. csr->DATA_TYPE_DISABLE_BF = 0U;
  126. #else
  127. csr->DATA_TYPE_DIS = 0U;
  128. #endif
  129. /* VC fence. */
  130. #if defined(MIPI_CSI_CSR_STREAM_FENCING_CONTROL_STREAM_FENCING_CONTROL_MASK)
  131. csr->STREAM_FENCING_CONTROL = 0U;
  132. #else
  133. csr->STREAM_FENCING_CTRL = 0U;
  134. #endif
  135. #if defined(MIPI_CSI_CSR_PLM_CTRL_PL_CLOCK_RUNNING_MASK)
  136. /* Wait for PL clock active. */
  137. while (0UL != (csr->PLM_CTRL & MIPI_CSI_CSR_PLM_CTRL_PL_CLOCK_RUNNING_MASK))
  138. {
  139. }
  140. #endif
  141. /* Enable pixel link master. */
  142. csr->PLM_CTRL |= (MIPI_CSI_CSR_PLM_CTRL_ENABLE_MASK | MIPI_CSI_CSR_PLM_CTRL_VALID_OVERRIDE_MASK);
  143. /* Power up PHY. */
  144. csr->PHY_CTRL &= ~MIPI_CSI_CSR_PHY_CTRL_PD_MASK;
  145. /* Start clock. */
  146. csr->CONTROLLER_CLOCK_RESET_CONTROL = MIPI_CSI_CSR_CONTROLLER_CLOCK_RESET_CONTROL_SW_RESET_MASK;
  147. }
  148. static void MIPI_CSI2RX_DeinitInterface(MIPI_CSI2RX_Type *base)
  149. {
  150. MIPI_CSI_CSR_Type *csr = CSI2RX_GET_CSR(base);
  151. /* Disable the PHY. */
  152. csr->PHY_CTRL = 0;
  153. /* Disable the pixel link master. */
  154. csr->PLM_CTRL = 0;
  155. /* Stop the clock and assert reset. */
  156. csr->CONTROLLER_CLOCK_RESET_CONTROL = MIPI_CSI_CSR_CONTROLLER_CLOCK_RESET_CONTROL_CTL_CLK_OFF_MASK;
  157. }
  158. #endif
  159. uint32_t CSI2RX_GetInstance(MIPI_CSI2RX_Type *base)
  160. {
  161. uint32_t i;
  162. for (i = 0U; i < ARRAY_SIZE(s_csi2rxBaseAddrs); i++)
  163. {
  164. if ((uint32_t)base == s_csi2rxBaseAddrs[i])
  165. {
  166. return i;
  167. }
  168. }
  169. assert(false);
  170. return 0;
  171. }
  172. /*!
  173. * brief Enables and configures the CSI2RX peripheral module.
  174. *
  175. * param base CSI2RX peripheral address.
  176. * param config CSI2RX module configuration structure.
  177. */
  178. void CSI2RX_Init(MIPI_CSI2RX_Type *base, const csi2rx_config_t *config)
  179. {
  180. assert(NULL != config);
  181. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  182. /* un-gate clock */
  183. (void)CLOCK_EnableClock(s_csi2rxClocks[CSI2RX_GetInstance(base)]);
  184. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  185. MIPI_CSI2RX_SoftwareReset(base, false);
  186. CSI2RX_REG_CFG_NUM_LANES(base) = config->laneNum - 1UL;
  187. CSI2RX_REG_CFG_DISABLE_DATA_LANES(base) =
  188. MIPI_CSI2RX_CSI2RX_CFG_NUM_LANES_csi2rx_cfg_num_lanes_MASK & ~((1UL << (uint32_t)config->laneNum) - 1UL);
  189. /* Don't disable data types. */
  190. CSI2RX_REG_CFG_DISABLE_PAYLOAD_0(base) = 0;
  191. CSI2RX_REG_CFG_DISABLE_PAYLOAD_1(base) = 0;
  192. /* Disable all interrupts. */
  193. CSI2RX_REG_IRQ_MASK(base) = MIPI_CSI2RX_CSI2RX_IRQ_MASK_csi2rx_irq_mask_MASK;
  194. MIPI_CSI2RX_InitInterface(base, config->tHsSettle_EscClk);
  195. }
  196. /*!
  197. * brief Disables the CSI2RX peripheral module.
  198. *
  199. * param base CSI2RX peripheral address.
  200. */
  201. void CSI2RX_Deinit(MIPI_CSI2RX_Type *base)
  202. {
  203. MIPI_CSI2RX_DeinitInterface(base);
  204. MIPI_CSI2RX_SoftwareReset(base, true);
  205. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  206. /* gate clock */
  207. (void)CLOCK_DisableClock(s_csi2rxClocks[CSI2RX_GetInstance(base)]);
  208. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  209. }