OpenSSD Cosmos+ Platform Firmware  0.0.2
The firmware of Cosmos+ OpenSSD Platform for TOSHIBA nand flash module.
nsc_driver.c
Go to the documentation of this file.
1
2// fmc_driver.c for Cosmos+ OpenSSD
3// Copyright (c) 2016 Hanyang University ENC Lab.
4// Contributed by Yong Ho Song <yhsong@enc.hanyang.ac.kr>
5// Kibin Park <kbpark@enc.hanyang.ac.kr>
6// Jaewook Kwak <jwkwak@enc.hanyang.ac.kr>
7//
8// This file is part of Cosmos+ OpenSSD.
9//
10// Cosmos+ OpenSSD is free software; you can redistribute it and/or modify
11// it under the terms of the GNU General Public License as published by
12// the Free Software Foundation; either version 3, or (at your option)
13// any later version.
14//
15// Cosmos+ OpenSSD is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18// See the GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with Cosmos+ OpenSSD; see the file COPYING.
22// If not, see <http://www.gnu.org/licenses/>.
24
26// Company: ENC Lab. <http://enc.hanyang.ac.kr>
27// Engineer: Kibin Park <kbpark@enc.hanyang.ac.kr>
28//
29// Project Name: Cosmos+ OpenSSD
30// Design Name: Cosmos+ Firmware
31// Module Name: NAND Storage Controller Driver
32// File Name: nsc_driver.c
33//
34// Version: v1.1.0
35//
36// Description:
37// - low level driver for NAND storage controller
39
41// Revision History:
42//
43// * v1.1.0
44// - V2FReadPageTransferAsync needs additional input (rowAddress)
45//
46// * v1.0.0
47// - First draft
49
50#include "nsc_driver.h"
51#include "xparameters.h"
52#include <assert.h>
53
54typedef struct
55{
56 unsigned char delayVal[32];
58
59void nfc_set_dqs_delay(int channel, unsigned int newValue)
60{
61 volatile unsigned int *ctrl0 = (volatile unsigned int *)XPAR_IODELAY_IF_0_DQS_BASEADDR;
62 volatile iodelay_if *data0 = (volatile iodelay_if *)(XPAR_IODELAY_IF_0_DQS_BASEADDR + 0x8000);
63 volatile unsigned int *ctrl1 = (volatile unsigned int *)XPAR_IODELAY_IF_1_DQS_BASEADDR;
64 volatile iodelay_if *data1 = (volatile iodelay_if *)(XPAR_IODELAY_IF_1_DQS_BASEADDR + 0x8000);
65
66 if (channel < 4)
67 {
68 data0->delayVal[channel] = newValue;
69 ctrl0[1] = 1;
70 }
71 else
72 {
73 data1->delayVal[channel % 4] = newValue;
74 ctrl1[1] = 1;
75 }
76}
77
78void nfc_set_dq_delay(int channel, unsigned int newValue)
79{
80 volatile unsigned int *ctrl0 = (volatile unsigned int *)XPAR_IODELAY_IF_0_BASEADDR;
81 volatile iodelay_if *data0 = (volatile iodelay_if *)(XPAR_IODELAY_IF_0_BASEADDR + 0x8000);
82 volatile unsigned int *ctrl1 = (volatile unsigned int *)XPAR_IODELAY_IF_0_BASEADDR;
83 volatile iodelay_if *data1 = (volatile iodelay_if *)(XPAR_IODELAY_IF_0_BASEADDR + 0x8000);
84
85 int i;
86 if (channel < 4)
87 {
88 for (i = 0; i < 8; i++)
89 data0->delayVal[channel * 8 + i] = newValue;
90 ctrl0[1] = 1;
91 }
92 else
93 {
94 for (i = 0; i < 8; i++)
95 data1->delayVal[(channel % 4) * 8 + i] = newValue;
96 ctrl1[1] = 1;
97 }
98}
99
100void V2FInitializeHandle(T4REGS *t4regs, void *t4nscRegisterBaseAddress)
101{
102 t4regs->t4regID = (T4REG_ID *)((unsigned int)t4nscRegisterBaseAddress + 0);
103 t4regs->t4regCFG = (T4REG_CFG *)((unsigned int)t4nscRegisterBaseAddress + 0x1000);
104 t4regs->t4regEXT = (T4REG_EXT *)((unsigned int)t4nscRegisterBaseAddress + 0x2000);
105 t4regs->t4regCC = (T4REG_CC *)((unsigned int)t4nscRegisterBaseAddress + 0x3000);
106 t4regs->t4regBP = (T4REG_BP *)((unsigned int)t4nscRegisterBaseAddress + 0x3800);
107 t4regs->t4regSP = (T4REG_SP *)((unsigned int)t4nscRegisterBaseAddress + 0x4000);
108}
109
110void __attribute__((optimize("O0"))) V2FSetScramblerState(T4REGS *t4regs, int enable)
111{
112 T4REG_CMD_SET_SCRAMBLER setScramblerCmd;
113
115
116 V2FFillRegisters(t4regs, T4REG_CMD_SET_SCRAMBLER, setScramblerCmd);
117 V2FIssueCommand(t4regs);
118}
119
120void __attribute__((optimize("O0"))) V2FResetSync(T4REGS *t4regs, int way)
121{
122 T4REG_CMD_NAND_RESET resetCmd;
123
125 resetCmd.waySelect = 1 << way;
126
127 while (V2FIsControllerBusy(t4regs))
128 ;
129 V2FFillRegisters(t4regs, T4REG_CMD_NAND_RESET, resetCmd);
130 V2FIssueCommand(t4regs);
131
132 while (V2FIsControllerBusy(t4regs))
133 ;
134 V2FSetScramblerState(t4regs, 0);
135}
136
137void __attribute__((optimize("O0")))
138V2FSetFeaturesT(T4REGS *t4regs, int way, unsigned int address, volatile unsigned int *payload)
139{
140 T4REG_CMD_SET_FEATURES setFeaturesCmd;
141
142 setFeaturesCmd.cmdSelect = T4NSC_CMD_SET_FEATUREST;
143 setFeaturesCmd.waySelect = 1 << way;
144 setFeaturesCmd.payloadAddress = (unsigned int)payload;
145 setFeaturesCmd.setFeaturesAddress = address;
146
147 V2FFillRegisters(t4regs, T4REG_CMD_SET_FEATURES, setFeaturesCmd);
148 V2FIssueCommand(t4regs);
149}
150
151void V2FGetReadyBusy(T4REGS *t4regs, unsigned int *report)
152{
153 T4REG_CMD_GET_READYBUSY getReadyBusyCmd;
154
155 getReadyBusyCmd.cmdSelect = T4NSC_CMD_GET_READYBUSY;
156 getReadyBusyCmd.reserved = 0;
157 getReadyBusyCmd.reportAddress = (unsigned int)report;
158
159 V2FFillRegisters(t4regs, T4REG_CMD_GET_READYBUSY, getReadyBusyCmd);
160 V2FIssueCommand(t4regs);
161}
162
163void __attribute__((optimize("O0")))
164V2FSetFeaturesSync(T4REGS *t4regs, int way, unsigned int feature0x02, unsigned int feature0x10,
165 unsigned int feature0x01, unsigned int payLoadAddr)
166{
167 volatile unsigned int *payload = (unsigned int *)payLoadAddr;
168 volatile unsigned int *status = (unsigned int *)(payLoadAddr + 4);
169
170 *payload = feature0x02;
171 while (V2FIsControllerBusy(t4regs))
172 ;
173 V2FSetFeaturesT(t4regs, way, 0x02, payload);
174 do
175 {
176 while (V2FIsControllerBusy(t4regs))
177 ;
178 V2FGetReadyBusy(t4regs, status);
179 while (!(*status & 1))
180 ;
181 *status >>= 16;
182 } while (!(*status & (1 << way)));
183
184 *payload = feature0x10;
185 while (V2FIsControllerBusy(t4regs))
186 ;
187 V2FSetFeaturesT(t4regs, way, 0x10, payload);
188 do
189 {
190 while (V2FIsControllerBusy(t4regs))
191 ;
192 V2FGetReadyBusy(t4regs, status);
193 while (!(*status & 1))
194 ;
195 *status >>= 16;
196 } while (!(*status & (1 << way)));
197
198 while (V2FIsControllerBusy(t4regs))
199 ;
200 V2FSetScramblerState(t4regs, 0);
212}
213
214void __attribute__((optimize("O0"))) V2FReadPageTriggerAsync(T4REGS *t4regs, int way, unsigned int rowAddress)
215{
216 T4REG_CMD_READ_PAGE_TRIGGER readPageTrigggerCmd;
217
218 readPageTrigggerCmd.cmdSelect = T4NSC_CMD_READ_PAGE_TRIGGER_PSLC;
219 readPageTrigggerCmd.waySelect = 1 << way;
220 readPageTrigggerCmd.rowAddress = rowAddress;
221
222 while (V2FIsControllerBusy(t4regs))
223 ;
224 V2FFillRegisters(t4regs, T4REG_CMD_READ_PAGE_TRIGGER, readPageTrigggerCmd);
225 V2FIssueCommand(t4regs);
226}
227
228void __attribute__((optimize("O0")))
229V2FReadPageTransferAsync(T4REGS *t4regs, int way, void *pageDataBuffer, void *spareDataBuffer,
230 unsigned int *errorInformation, unsigned int *completion, unsigned int rowAddress)
231{
233
235 readpagepSLC.waySelect = 1 << way;
236 readpagepSLC.rowAddress = rowAddress;
237 readpagepSLC.pageDataAddress = pageDataBuffer;
238 readpagepSLC.spareDataAddress = spareDataBuffer;
239 readpagepSLC.errorInfoAddress = errorInformation;
240 *completion = 0;
241 readpagepSLC.completionReportAddress = completion;
242
243 while (V2FIsControllerBusy(t4regs))
244 ;
246 V2FIssueCommand(t4regs);
247}
248
249void __attribute__((optimize("O0")))
250V2FReadPageTransferRawAsync(T4REGS *t4regs, int way, void *pageDataBuffer, unsigned int *completion)
251{
252 T4REG_CMD_READ_PAGE_TRANSFER_RAW readPageTransferRaw;
253
254 readPageTransferRaw.cmdSelect = T4NSC_CMD_READ_TRANSFER_RAW;
255 readPageTransferRaw.waySelect = 1 << way;
256 readPageTransferRaw.colAddress = 0;
257 readPageTransferRaw.wordLength = (16384 + 1664) / 4;
258 readPageTransferRaw.pageDataAddress = pageDataBuffer;
259 readPageTransferRaw.completionReportAddress = (unsigned int)completion;
260 *completion = 0;
261
262 while (V2FIsControllerBusy(t4regs))
263 ;
264 V2FFillRegisters(t4regs, T4REG_CMD_READ_PAGE_TRANSFER_RAW, readPageTransferRaw);
265 V2FIssueCommand(t4regs);
266}
267
268void __attribute__((optimize("O0")))
269V2FProgramPageAsync(T4REGS *t4regs, int way, unsigned int rowAddress, void *pageDataBuffer, void *spareDataBuffer)
270{
272
274 progPagepSLC.waySelect = 1 << way;
275 progPagepSLC.rowAddress = rowAddress;
276 progPagepSLC.pageDataAddress = pageDataBuffer;
277 progPagepSLC.spareDataAddress = spareDataBuffer;
278
279 while (V2FIsControllerBusy(t4regs))
280 ;
282 V2FIssueCommand(t4regs);
283}
284
285void __attribute__((optimize("O0"))) V2FEraseBlockAsync(T4REGS *t4regs, int way, unsigned int rowAddress)
286{
287 T4REG_CMD_ERASE_BLOCK eraseBlockCmd;
288
289 assert((rowAddress & 0xFF) == 0);
290
291 eraseBlockCmd.cmdSelect = T4NSC_CMD_ERASE_BLOCK;
292 eraseBlockCmd.waySelect = 1 << way;
293 eraseBlockCmd.rowAddress = rowAddress;
294
295 while (V2FIsControllerBusy(t4regs))
296 ;
297 V2FFillRegisters(t4regs, T4REG_CMD_ERASE_BLOCK, eraseBlockCmd);
298 V2FIssueCommand(t4regs);
299}
300
301void __attribute__((optimize("O0"))) V2FStatusCheckAsync(T4REGS *t4regs, int way, unsigned int *statusReport)
302{
303 T4REG_CMD_READ_STATUS readStatusCmd;
304
305 readStatusCmd.cmdSelect = T4NSC_CMD_READ_STATUS;
306 readStatusCmd.waySelect = 1 << way;
307 readStatusCmd.reportAddress = (unsigned int)statusReport;
308 *statusReport = 0;
309
310 while (V2FIsControllerBusy(t4regs))
311 ;
312 V2FFillRegisters(t4regs, T4REG_CMD_READ_STATUS, readStatusCmd);
313 V2FIssueCommand(t4regs);
314}
315
316void V2FReadIdAsync(T4REGS *t4regs, int way, unsigned int *statusReport, unsigned int *completion)
317{
318 T4REG_CMD_READ_ID readIdCmd;
319
320 readIdCmd.cmdSelect = T4NSC_CMD_READ_ID;
321 readIdCmd.waySelect = 1 << way;
322 readIdCmd.colAddress = 0x0090;
323 readIdCmd.length = 3;
324 readIdCmd.reportAddress = (unsigned int)statusReport;
325 readIdCmd.completionReportAddress = (unsigned int)completion;
326
327 while (V2FIsControllerBusy(t4regs))
328 ;
329 V2FFillRegisters(t4regs, T4REG_CMD_READ_ID, readIdCmd);
330 V2FIssueCommand(t4regs);
331}
332
333void V2FReadIdSync(T4REGS *t4regs, int way, unsigned int *statusReport)
334{
335 unsigned char buf[8] = {0};
336 int i;
337 for (i = 0; i < 8; i++)
338 ((unsigned char *)statusReport)[i] = 0;
339 unsigned int *completion = &statusReport[4];
340 *completion = 0;
341 V2FReadIdAsync(t4regs, way, statusReport, completion);
342 while (*completion == 0)
343 ;
344
345 for (i = 0; i < 6; i++)
346 buf[i] = ((unsigned char *)statusReport)[i * 2];
347 for (i = 0; i < 8; i++)
348 ((unsigned char *)statusReport)[i] = buf[i];
349}
350
351unsigned int __attribute__((optimize("O0"))) V2FReadyBusyAsync(T4REGS *t4regs)
352{
353 volatile unsigned int readyBusy = (t4regs)->t4regBP->nandReadyBusy;
354
355 return readyBusy;
356}
#define XPAR_IODELAY_IF_0_BASEADDR
Definition: bsp.h:12
#define XPAR_IODELAY_IF_0_DQS_BASEADDR
Definition: bsp.h:14
#define XPAR_IODELAY_IF_1_DQS_BASEADDR
Definition: bsp.h:15
void __attribute__((optimize("O0")))
Definition: nsc_driver.c:110
void V2FGetReadyBusy(T4REGS *t4regs, unsigned int *report)
Definition: nsc_driver.c:151
void V2FInitializeHandle(T4REGS *t4regs, void *t4nscRegisterBaseAddress)
Definition: nsc_driver.c:100
void V2FReadIdAsync(T4REGS *t4regs, int way, unsigned int *statusReport, unsigned int *completion)
Definition: nsc_driver.c:316
void nfc_set_dq_delay(int channel, unsigned int newValue)
Definition: nsc_driver.c:78
void nfc_set_dqs_delay(int channel, unsigned int newValue)
Definition: nsc_driver.c:59
void V2FReadIdSync(T4REGS *t4regs, int way, unsigned int *statusReport)
Definition: nsc_driver.c:333
void V2FReadPageTransferAsync(T4REGS *t4regs, int way, void *pageDataBuffer, void *spareDataBuffer, unsigned int *errorInformation, unsigned int *completion, unsigned int rowAddress)
void V2FReadPageTransferRawAsync(T4REGS *t4regs, int way, void *pageDataBuffer, unsigned int *completion)
#define V2FIssueCommand(t4regs)
Definition: nsc_driver.h:98
void V2FReadPageTriggerAsync(T4REGS *t4regs, int way, unsigned int rowAddress)
#define T4NSC_CMD_ERASE_BLOCK
Definition: nsc_driver.h:73
#define T4NSC_CMD_READ_TRANSFER_RAW
Definition: nsc_driver.h:83
#define V2FIsControllerBusy(t4regs)
Definition: nsc_driver.h:100
#define T4NSC_CMD_SET_SCRAMBLER_ENABLE
Definition: nsc_driver.h:71
void V2FStatusCheckAsync(T4REGS *t4regs, int way, unsigned int *statusReport)
#define T4NSC_CMD_READ_ID
Definition: nsc_driver.h:87
void V2FEraseBlockAsync(T4REGS *t4regs, int way, unsigned int rowAddress)
#define T4NSC_CMD_SET_FEATUREST
Definition: nsc_driver.h:67
#define T4NSC_CMD_SET_SCRAMBLER_DISABLE
Definition: nsc_driver.h:70
#define T4NSC_CMD_NAND_RESET
Definition: nsc_driver.h:62
#define T4NSC_CMD_READ_PAGE_TRIGGER_PSLC
Definition: nsc_driver.h:82
void V2FSetFeaturesSync(T4REGS *t4regs, int way, unsigned int feature0x02, unsigned int feature0x10, unsigned int feature0x01, unsigned int payLoadAddr)
void V2FProgramPageAsync(T4REGS *t4regs, int way, unsigned int rowAddress, void *pageDataBuffer, void *spareDataBuffer)
#define T4NSC_CMD_READ_TRANSFER_PSLC
Definition: nsc_driver.h:90
#define T4NSC_CMD_GET_READYBUSY
Definition: nsc_driver.h:64
#define T4NSC_CMD_READ_STATUS
Definition: nsc_driver.h:72
#define T4NSC_CMD_PROGRAM_PAGE_PSLC
Definition: nsc_driver.h:91
#define V2FFillRegisters(t4regs, cmdtype, cmdpayload)
Definition: nsc_driver.h:97
unsigned int V2FReadyBusyAsync(T4REGS *t4regs)
void V2FResetSync(T4REGS *t4regs, int way)
volatile T4REG_CC * t4regCC
Definition: nsc_driver.h:175
volatile T4REG_BP * t4regBP
Definition: nsc_driver.h:177
volatile T4REG_ID * t4regID
Definition: nsc_driver.h:169
volatile T4REG_EXT * t4regEXT
Definition: nsc_driver.h:173
volatile T4REG_CFG * t4regCFG
Definition: nsc_driver.h:171
volatile T4REG_SP * t4regSP
Definition: nsc_driver.h:179
unsigned int cmdSelect
Definition: nsc_driver.h:252
unsigned int rowAddress
Definition: nsc_driver.h:254
unsigned int waySelect
Definition: nsc_driver.h:253
unsigned int reportAddress
Definition: nsc_driver.h:225
unsigned int cmdSelect
Definition: nsc_driver.h:223
unsigned int reserved
Definition: nsc_driver.h:224
unsigned int cmdSelect
Definition: nsc_driver.h:184
unsigned int waySelect
Definition: nsc_driver.h:185
unsigned int length
Definition: nsc_driver.h:412
unsigned int completionReportAddress
Definition: nsc_driver.h:414
unsigned int waySelect
Definition: nsc_driver.h:410
unsigned int reportAddress
Definition: nsc_driver.h:413
unsigned int cmdSelect
Definition: nsc_driver.h:409
unsigned int colAddress
Definition: nsc_driver.h:411
unsigned int waySelect
Definition: nsc_driver.h:246
unsigned int reportAddress
Definition: nsc_driver.h:247
unsigned int cmdSelect
Definition: nsc_driver.h:245
unsigned int setFeaturesAddress
Definition: nsc_driver.h:200
unsigned int waySelect
Definition: nsc_driver.h:198
unsigned int cmdSelect
Definition: nsc_driver.h:197
unsigned int payloadAddress
Definition: nsc_driver.h:199
unsigned int cmdSelect
Definition: nsc_driver.h:240
unsigned char delayVal[32]
Definition: nsc_driver.c:56