Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:00

0001 /*
0002  * Copyright 2017, 2019-2020 NXP
0003  * All rights reserved.
0004  *
0005  *
0006  * SPDX-License-Identifier: BSD-3-Clause
0007  */
0008 
0009 #include "fsl_mipi_csi2rx.h"
0010 
0011 /*
0012  * The MIPI CSI2 peripheral can not work independently, some other control and
0013  * status registers must be used together. There are two integration methods
0014  * with these registers.
0015  *
0016  * 1. The registers are collected in one dedicated module: CSR.
0017  * 2. The registers are scattered in multiple modules.
0018  *
0019  */
0020 
0021 /*******************************************************************************
0022  * Definitions
0023  ******************************************************************************/
0024 
0025 /* Component ID definition, used by tools. */
0026 #ifndef FSL_COMPONENT_ID
0027 #define FSL_COMPONENT_ID "platform.drivers.mipi_csi2rx"
0028 #endif
0029 
0030 #if (defined(FSL_FEATURE_CSI2RX_CSR_OFFSET) && FSL_FEATURE_CSI2RX_CSR_OFFSET)
0031 #define CSI2RX_GET_CSR(csi_base) (MIPI_CSI_CSR_Type *)((uint32_t)(csi_base) - (uint32_t)FSL_FEATURE_CSI2RX_CSR_OFFSET)
0032 #define MIPI_CSI2RX_HAS_CSR      1
0033 #else
0034 #define MIPI_CSI2RX_HAS_CSR 0
0035 #include "fsl_soc_mipi_csi2rx.h"
0036 #endif
0037 
0038 #if MIPI_CSI2RX_HAS_CSR
0039 
0040 /* Macro Map */
0041 #ifndef MIPI_CSI_CSR_CONTROLLER_CLOCK_RESET_CONTROL_CTL_CLK_OFF_MASK
0042 #define MIPI_CSI_CSR_CONTROLLER_CLOCK_RESET_CONTROL_CTL_CLK_OFF_MASK \
0043     MIPI_CSI_CSR_CONTROLLER_CLOCK_RESET_CONTROL_CONTROLLER_CLOCK_RESET_CONTROL(2U)
0044 #define MIPI_CSI_CSR_CONTROLLER_CLOCK_RESET_CONTROL_SW_RESET_MASK \
0045     MIPI_CSI_CSR_CONTROLLER_CLOCK_RESET_CONTROL_CONTROLLER_CLOCK_RESET_CONTROL(1U)
0046 #endif
0047 
0048 #ifndef MIPI_CSI_CSR_PHY_CTRL_CONTI_CLK_MODE_MASK
0049 #define MIPI_CSI_CSR_PHY_CTRL_CONTI_CLK_MODE_MASK MIPI_CSI_CSR_PHY_CTRL_CONT_CLK_MODE_MASK
0050 #endif
0051 
0052 #ifndef MIPI_CSI_CSR_PHY_CTRL_PRG_RXHS_SETTLE
0053 #define MIPI_CSI_CSR_PHY_CTRL_PRG_RXHS_SETTLE(x) MIPI_CSI_CSR_PHY_CTRL_S_PRG_RXHS_SETTLE(x)
0054 #endif
0055 
0056 #endif
0057 
0058 /*******************************************************************************
0059  * Prototypes
0060  ******************************************************************************/
0061 
0062 /*!
0063  * @brief Returns an instance number given a base address.
0064  *
0065  * If an invalid base address is passed, debug builds will assert. Release builds will just return
0066  * instance number 0.
0067  *
0068  * @param base The CSI2RX peripheral base address.
0069  * @return CSI2RX instance number starting from 0.
0070  */
0071 uint32_t CSI2RX_GetInstance(MIPI_CSI2RX_Type *base);
0072 
0073 #if MIPI_CSI2RX_HAS_CSR
0074 
0075 /*!
0076  * @brief Perform CSI2RX resource reset in system level.
0077  *
0078  * @param base The CSI2RX peripheral base address.
0079  * @param reset Pass in true to set to reset state, false to release reset.
0080  */
0081 static void MIPI_CSI2RX_SoftwareReset(MIPI_CSI2RX_Type *base, bool reset);
0082 
0083 /*!
0084  * @brief Initialize the CSI2RX interface.
0085  *
0086  * @param base The CSI2RX peripheral base address.
0087  * @param tHsSettle_EscClk t-HS_SETTLE in esc clock period.
0088  */
0089 static void MIPI_CSI2RX_InitInterface(MIPI_CSI2RX_Type *base, uint8_t tHsSettle_EscClk);
0090 
0091 /*!
0092  * @brief Deinitialize the CSI2RX interface.
0093  *
0094  * @param base The CSI2RX peripheral base address.
0095  */
0096 static void MIPI_CSI2RX_DeinitInterface(MIPI_CSI2RX_Type *base);
0097 
0098 #endif
0099 
0100 /*******************************************************************************
0101  * Variables
0102  ******************************************************************************/
0103 
0104 /*! @brief Array to map MIPI CSI2RX instance number to base address. */
0105 static const uint32_t s_csi2rxBaseAddrs[] = MIPI_CSI2RX_BASE_ADDRS;
0106 
0107 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0108 /*! @brief Pointers to MPI CSI2RX clocks for each instance. */
0109 static const clock_ip_name_t s_csi2rxClocks[] = MIPI_CSI2RX_CLOCKS;
0110 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0111 
0112 /*******************************************************************************
0113  * Code
0114  ******************************************************************************/
0115 
0116 #if MIPI_CSI2RX_HAS_CSR
0117 static void MIPI_CSI2RX_SoftwareReset(MIPI_CSI2RX_Type *base, bool reset)
0118 {
0119     MIPI_CSI_CSR_Type *csr = CSI2RX_GET_CSR(base);
0120 
0121     if (reset)
0122     {
0123         csr->CONTROLLER_CLOCK_RESET_CONTROL = MIPI_CSI_CSR_CONTROLLER_CLOCK_RESET_CONTROL_CTL_CLK_OFF_MASK;
0124     }
0125     else
0126     {
0127         csr->CONTROLLER_CLOCK_RESET_CONTROL = MIPI_CSI_CSR_CONTROLLER_CLOCK_RESET_CONTROL_CTL_CLK_OFF_MASK;
0128         csr->CONTROLLER_CLOCK_RESET_CONTROL = MIPI_CSI_CSR_CONTROLLER_CLOCK_RESET_CONTROL_SW_RESET_MASK |
0129                                               MIPI_CSI_CSR_CONTROLLER_CLOCK_RESET_CONTROL_CTL_CLK_OFF_MASK;
0130     }
0131 }
0132 
0133 static void MIPI_CSI2RX_InitInterface(MIPI_CSI2RX_Type *base, uint8_t tHsSettle_EscClk)
0134 {
0135     MIPI_CSI_CSR_Type *csr = CSI2RX_GET_CSR(base);
0136 
0137     /* Pixel link control */
0138     csr->PLM_CTRL = 0;
0139 
0140     /* Configure the PHY. */
0141     csr->PHY_CTRL = MIPI_CSI_CSR_PHY_CTRL_RX_ENABLE_MASK |  /* Enable RX. */
0142                     MIPI_CSI_CSR_PHY_CTRL_AUTO_PD_EN_MASK | /* Auto power down unused lanes. */
0143                     MIPI_CSI_CSR_PHY_CTRL_PD_MASK | MIPI_CSI_CSR_PHY_CTRL_DDRCLK_EN_MASK | /* Enable the DDR clock. */
0144                     MIPI_CSI_CSR_PHY_CTRL_CONTI_CLK_MODE_MASK |                            /* Continue clock. */
0145                     MIPI_CSI_CSR_PHY_CTRL_RTERM_SEL_MASK | /*  LPRX voltage level enable HS termination */
0146                     MIPI_CSI_CSR_PHY_CTRL_PRG_RXHS_SETTLE(tHsSettle_EscClk - 1UL); /* T(HS-SETTLE) */
0147 
0148     /* Don't support interlace currently. */
0149     csr->VC_INTERLACED = 0U;
0150 
0151     /* Don't mask any data type */
0152 #if defined(MIPI_CSI_CSR_DATA_TYPE_DISABLE_BF_DATA_TYPE_DISABLE_MASK)
0153     csr->DATA_TYPE_DISABLE_BF = 0U;
0154 #else
0155     csr->DATA_TYPE_DIS       = 0U;
0156 #endif
0157 
0158     /* VC fence. */
0159 #if defined(MIPI_CSI_CSR_STREAM_FENCING_CONTROL_STREAM_FENCING_CONTROL_MASK)
0160     csr->STREAM_FENCING_CONTROL = 0U;
0161 #else
0162     csr->STREAM_FENCING_CTRL = 0U;
0163 #endif
0164 
0165 #if defined(MIPI_CSI_CSR_PLM_CTRL_PL_CLOCK_RUNNING_MASK)
0166     /* Wait for PL clock active. */
0167     while (0UL != (csr->PLM_CTRL & MIPI_CSI_CSR_PLM_CTRL_PL_CLOCK_RUNNING_MASK))
0168     {
0169     }
0170 #endif
0171 
0172     /* Enable pixel link master. */
0173     csr->PLM_CTRL |= (MIPI_CSI_CSR_PLM_CTRL_ENABLE_MASK | MIPI_CSI_CSR_PLM_CTRL_VALID_OVERRIDE_MASK);
0174 
0175     /* Power up PHY. */
0176     csr->PHY_CTRL &= ~MIPI_CSI_CSR_PHY_CTRL_PD_MASK;
0177 
0178     /* Start clock. */
0179     csr->CONTROLLER_CLOCK_RESET_CONTROL = MIPI_CSI_CSR_CONTROLLER_CLOCK_RESET_CONTROL_SW_RESET_MASK;
0180 }
0181 
0182 static void MIPI_CSI2RX_DeinitInterface(MIPI_CSI2RX_Type *base)
0183 {
0184     MIPI_CSI_CSR_Type *csr = CSI2RX_GET_CSR(base);
0185 
0186     /* Disable the PHY. */
0187     csr->PHY_CTRL = 0;
0188 
0189     /* Disable the pixel link master. */
0190     csr->PLM_CTRL = 0;
0191 
0192     /* Stop the clock and assert reset. */
0193     csr->CONTROLLER_CLOCK_RESET_CONTROL = MIPI_CSI_CSR_CONTROLLER_CLOCK_RESET_CONTROL_CTL_CLK_OFF_MASK;
0194 }
0195 #endif
0196 
0197 uint32_t CSI2RX_GetInstance(MIPI_CSI2RX_Type *base)
0198 {
0199     uint32_t i;
0200 
0201     for (i = 0U; i < ARRAY_SIZE(s_csi2rxBaseAddrs); i++)
0202     {
0203         if ((uint32_t)base == s_csi2rxBaseAddrs[i])
0204         {
0205             return i;
0206         }
0207     }
0208 
0209     assert(false);
0210 
0211     return 0;
0212 }
0213 
0214 /*!
0215  * brief Enables and configures the CSI2RX peripheral module.
0216  *
0217  * param base CSI2RX peripheral address.
0218  * param config CSI2RX module configuration structure.
0219  */
0220 void CSI2RX_Init(MIPI_CSI2RX_Type *base, const csi2rx_config_t *config)
0221 {
0222     assert(NULL != config);
0223 
0224 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0225     /* un-gate clock */
0226     (void)CLOCK_EnableClock(s_csi2rxClocks[CSI2RX_GetInstance(base)]);
0227 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0228 
0229     MIPI_CSI2RX_SoftwareReset(base, false);
0230 
0231     CSI2RX_REG_CFG_NUM_LANES(base) = config->laneNum - 1UL;
0232     CSI2RX_REG_CFG_DISABLE_DATA_LANES(base) =
0233         MIPI_CSI2RX_CSI2RX_CFG_NUM_LANES_csi2rx_cfg_num_lanes_MASK & ~((1UL << (uint32_t)config->laneNum) - 1UL);
0234 
0235     /* Don't disable data types. */
0236     CSI2RX_REG_CFG_DISABLE_PAYLOAD_0(base) = 0;
0237     CSI2RX_REG_CFG_DISABLE_PAYLOAD_1(base) = 0;
0238 
0239     /* Disable all interrupts. */
0240     CSI2RX_REG_IRQ_MASK(base) = MIPI_CSI2RX_CSI2RX_IRQ_MASK_csi2rx_irq_mask_MASK;
0241 
0242     MIPI_CSI2RX_InitInterface(base, config->tHsSettle_EscClk);
0243 }
0244 
0245 /*!
0246  * brief Disables the CSI2RX peripheral module.
0247  *
0248  * param base CSI2RX peripheral address.
0249  */
0250 void CSI2RX_Deinit(MIPI_CSI2RX_Type *base)
0251 {
0252     MIPI_CSI2RX_DeinitInterface(base);
0253 
0254     MIPI_CSI2RX_SoftwareReset(base, true);
0255 
0256 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
0257     /* gate clock */
0258     (void)CLOCK_DisableClock(s_csi2rxClocks[CSI2RX_GetInstance(base)]);
0259 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
0260 }