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