1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2019 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_spifi.h"
10 
11 /*******************************************************************************
12  * Definitions
13  ******************************************************************************/
14 
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.spifi"
18 #endif
19 
20 /*******************************************************************************
21  * Prototypes
22  ******************************************************************************/
23 
24 /*******************************************************************************
25  * Variables
26  ******************************************************************************/
27 
28 /* Array of SPIFI peripheral base address. */
29 static SPIFI_Type *const s_spifiBases[] = SPIFI_BASE_PTRS;
30 
31 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
32 /* Array of SPIFI clock name. */
33 static const clock_ip_name_t s_spifiClock[] = SPIFI_CLOCKS;
34 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
35 
36 #if !(defined(FSL_FEATURE_SPIFI_HAS_NO_RESET) && FSL_FEATURE_SPIFI_HAS_NO_RESET)
37 static const reset_ip_name_t s_spifiResets[] = SPIFI_RSTS;
38 #endif
39 
40 /*******************************************************************************
41  * Code
42  ******************************************************************************/
43 /*!
44  * brief Get the SPIFI instance from peripheral base address.
45  *
46  * param base SPIFI peripheral base address.
47  * return SPIFI instance.
48  */
SPIFI_GetInstance(SPIFI_Type * base)49 uint32_t SPIFI_GetInstance(SPIFI_Type *base)
50 {
51     uint32_t instance;
52 
53     /* Find the instance index from base address mappings. */
54     for (instance = 0; instance < ARRAY_SIZE(s_spifiBases); instance++)
55     {
56         if (s_spifiBases[instance] == base)
57         {
58             break;
59         }
60     }
61 
62     assert(instance < ARRAY_SIZE(s_spifiBases));
63 
64     return instance;
65 }
66 
67 /*!
68  * brief Get SPIFI default configure settings.
69  *
70  * param config  SPIFI config structure pointer.
71  */
SPIFI_GetDefaultConfig(spifi_config_t * config)72 void SPIFI_GetDefaultConfig(spifi_config_t *config)
73 {
74     assert(config != NULL);
75 
76     /* Initializes the configure structure to zero. */
77     (void)memset(config, 0, sizeof(*config));
78 
79     config->timeout              = 0xFFFFU;
80     config->csHighTime           = 0xFU;
81     config->disablePrefetch      = false;
82     config->disableCachePrefech  = false;
83     config->isFeedbackClock      = true;
84     config->spiMode              = kSPIFI_SPISckLow;
85     config->isReadFullClockCycle = true;
86     config->dualMode             = kSPIFI_QuadMode;
87 }
88 
89 /*!
90  * brief Initializes the SPIFI with the user configuration structure.
91  *
92  * This function configures the SPIFI module with the user-defined configuration.
93  *
94  * param base     SPIFI peripheral base address.
95  * param config   The pointer to the configuration structure.
96  */
SPIFI_Init(SPIFI_Type * base,const spifi_config_t * config)97 void SPIFI_Init(SPIFI_Type *base, const spifi_config_t *config)
98 {
99     assert(config != NULL);
100 
101 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
102     /* Enable the SAI clock */
103     CLOCK_EnableClock(s_spifiClock[SPIFI_GetInstance(base)]);
104 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
105 
106 #if !(defined(FSL_FEATURE_SPIFI_HAS_NO_RESET) && FSL_FEATURE_SPIFI_HAS_NO_RESET)
107     RESET_PeripheralReset(s_spifiResets[SPIFI_GetInstance(base)]);
108 #endif
109 
110     /* Reset the Command register */
111     SPIFI_ResetCommand(base);
112 
113     /* Set time delay parameter */
114     base->CTRL = SPIFI_CTRL_TIMEOUT(config->timeout) | SPIFI_CTRL_CSHIGH(config->csHighTime) |
115                  SPIFI_CTRL_D_PRFTCH_DIS(config->disablePrefetch) | SPIFI_CTRL_MODE3(config->spiMode) |
116                  SPIFI_CTRL_PRFTCH_DIS(config->disableCachePrefech) | SPIFI_CTRL_DUAL(config->dualMode) |
117                  SPIFI_CTRL_RFCLK(config->isReadFullClockCycle) | SPIFI_CTRL_FBCLK(config->isFeedbackClock);
118 }
119 
120 /*!
121  * brief Deinitializes the SPIFI regions.
122  *
123  * param base     SPIFI peripheral base address.
124  */
SPIFI_Deinit(SPIFI_Type * base)125 void SPIFI_Deinit(SPIFI_Type *base)
126 {
127 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
128     /* Enable the SAI clock */
129     CLOCK_DisableClock(s_spifiClock[SPIFI_GetInstance(base)]);
130 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
131 }
132 
133 /*!
134  * brief Set SPIFI flash command.
135  *
136  * param base     SPIFI peripheral base address.
137  * param cmd      SPIFI command structure pointer.
138  */
SPIFI_SetCommand(SPIFI_Type * base,spifi_command_t * cmd)139 void SPIFI_SetCommand(SPIFI_Type *base, spifi_command_t *cmd)
140 {
141     /* If SPIFI in memory mode, call reset function to abort memory mode */
142     if ((SPIFI_GetStatusFlag(base) & SPIFI_STAT_MCINIT_MASK) != 0x00U)
143     {
144         SPIFI_ResetCommand(base);
145     }
146 
147     /* Wait for other command finished */
148     while ((SPIFI_GetStatusFlag(base) & SPIFI_STAT_CMD_MASK) != 0x00U)
149     {
150     }
151 
152     base->CMD = SPIFI_CMD_DATALEN(cmd->dataLen) | SPIFI_CMD_POLL(cmd->isPollMode) | SPIFI_CMD_DOUT(cmd->direction) |
153                 SPIFI_CMD_INTLEN(cmd->intermediateBytes) | SPIFI_CMD_FIELDFORM(cmd->format) |
154                 SPIFI_CMD_FRAMEFORM(cmd->type) | SPIFI_CMD_OPCODE(cmd->opcode);
155 }
156 
157 /*!
158  * brief Set SPIFI flash AHB read command.
159  *
160  * Call this function means SPIFI enters to memory mode, while users need to use command, a SPIFI_ResetCommand shall
161  * be called.
162  *
163  * param base     SPIFI peripheral base address.
164  * param cmd      SPIFI command structure pointer.
165  */
SPIFI_SetMemoryCommand(SPIFI_Type * base,spifi_command_t * cmd)166 void SPIFI_SetMemoryCommand(SPIFI_Type *base, spifi_command_t *cmd)
167 {
168     /* Wait for the CMD flag be 0 */
169     while ((SPIFI_GetStatusFlag(base) & SPIFI_STAT_CMD_MASK) != 0x00U)
170     {
171     }
172 
173     base->MCMD = SPIFI_MCMD_POLL(0U) | SPIFI_MCMD_DOUT(0U) | SPIFI_MCMD_INTLEN(cmd->intermediateBytes) |
174                  SPIFI_MCMD_FIELDFORM(cmd->format) | SPIFI_MCMD_FRAMEFORM(cmd->type) | SPIFI_MCMD_OPCODE(cmd->opcode);
175 
176     /* Wait for the command written */
177     while ((base->STAT & SPIFI_STAT_MCINIT_MASK) == 0x00U)
178     {
179     }
180 }
181 
182 /*!
183  * brief Write a halfword data in address of SPIFI.
184  *
185  * Users can write a halfword data into SPIFI address.
186  *
187  * param base     SPIFI peripheral base address.
188  * param data     Data need be write.
189  */
SPIFI_WriteDataHalfword(SPIFI_Type * base,uint16_t data)190 void SPIFI_WriteDataHalfword(SPIFI_Type *base, uint16_t data)
191 {
192     volatile uint8_t *dataReg = ((volatile uint8_t *)(&(base->DATA)));
193 
194     *dataReg = ((uint8_t)data & 0xFFU);
195     dataReg++;
196     *dataReg = (((uint8_t)(data >> 8U)) & 0xFFU);
197 }
198 
199 /*!
200  * brief Read a halfword data from serial flash.
201  *
202  * param base     SPIFI peripheral base address.
203  * return Data input from flash.
204  */
SPIFI_ReadDataHalfword(SPIFI_Type * base)205 uint16_t SPIFI_ReadDataHalfword(SPIFI_Type *base)
206 {
207     uint16_t val              = 0;
208     volatile uint8_t *dataReg = ((volatile uint8_t *)(&(base->DATA)));
209     uint8_t temp1             = *dataReg;
210     uint8_t temp2             = *(dataReg + 0x01U);
211 
212     val = temp1 | ((uint16_t)temp2) << 8U;
213 
214     return val;
215 }
216