|
| 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/>. |
| 23 | +////////////////////////////////////////////////////////////////////////////////// |
| 24 | + |
| 25 | +////////////////////////////////////////////////////////////////////////////////// |
| 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: Low Level Driver |
| 32 | +// File Name: fmc_driver.c |
| 33 | +// |
| 34 | +// Version: v1.1.0 |
| 35 | +// |
| 36 | +// Description: |
| 37 | +// - low level driver for V2 flash memory controller |
| 38 | +////////////////////////////////////////////////////////////////////////////////// |
| 39 | + |
| 40 | +////////////////////////////////////////////////////////////////////////////////// |
| 41 | +// Revision History: |
| 42 | +// |
| 43 | +// * v1.1.0 |
| 44 | +// - V2FReadPageTransferAsync needs additional input (rowAddress) |
| 45 | +// |
| 46 | +// * v1.0.0 |
| 47 | +// - First draft |
| 48 | +////////////////////////////////////////////////////////////////////////////////// |
| 49 | + |
| 50 | +#include "fmc_driver.h" |
| 51 | + |
| 52 | +unsigned int __attribute__((optimize("O0"))) V2FIsControllerBusy(V2FMCRegisters* dev) |
| 53 | +{ |
| 54 | + volatile unsigned int channelBusy = *((volatile unsigned int*)&(dev->channelBusy)); |
| 55 | + |
| 56 | + return channelBusy; |
| 57 | +} |
| 58 | + |
| 59 | +void __attribute__((optimize("O0"))) V2FResetSync(V2FMCRegisters* dev, int way) |
| 60 | +{ |
| 61 | + *((volatile unsigned int*)&(dev->waySelection)) = way; |
| 62 | + *((volatile unsigned int*)&(dev->cmdSelect)) = V2FCommand_Reset; |
| 63 | + while (V2FIsControllerBusy(dev)); |
| 64 | +} |
| 65 | + |
| 66 | +void __attribute__((optimize("O0"))) V2FSetFeaturesSync(V2FMCRegisters* dev, int way, unsigned int feature0x02, unsigned int feature0x10, unsigned int feature0x01, unsigned int payLoadAddr) |
| 67 | +{ |
| 68 | + unsigned int* payload = (unsigned int*)payLoadAddr; |
| 69 | + payload[0] = feature0x02; |
| 70 | + payload[1] = feature0x10; |
| 71 | + payload[2] = feature0x01; |
| 72 | + *((volatile unsigned int*)&(dev->waySelection)) = way; |
| 73 | + *((volatile unsigned int*)&(dev->userData)) = (unsigned int)payload; |
| 74 | + *((volatile unsigned int*)&(dev->cmdSelect)) = V2FCommand_SetFeatures; |
| 75 | + while (V2FIsControllerBusy(dev)); |
| 76 | +} |
| 77 | + |
| 78 | +void __attribute__((optimize("O0"))) V2FGetFeaturesSync(V2FMCRegisters* dev, int way, unsigned int* feature0x01, unsigned int* feature0x02, unsigned int* feature0x10, unsigned int* feature0x30) |
| 79 | +{ |
| 80 | + volatile unsigned int buffer[4] = {0}; |
| 81 | + volatile unsigned int completion = 0; |
| 82 | + *((volatile unsigned int*)&(dev->waySelection)) = way; |
| 83 | + *((volatile unsigned int*)&(dev->userData)) = (unsigned int)buffer; |
| 84 | + *((volatile unsigned int*)&(dev->completionAddress)) = (unsigned int)&completion; |
| 85 | + *((volatile unsigned int*)&(dev->cmdSelect)) = V2FCommand_GetFeatures; |
| 86 | + while (V2FIsControllerBusy(dev)); |
| 87 | + while (!(completion & 1)); |
| 88 | + *feature0x01 = buffer[0]; |
| 89 | + *feature0x02 = buffer[1]; |
| 90 | + *feature0x10 = buffer[2]; |
| 91 | + *feature0x30 = buffer[3]; |
| 92 | +} |
| 93 | + |
| 94 | +void __attribute__((optimize("O0"))) V2FReadPageTriggerAsync(V2FMCRegisters* dev, int way, unsigned int rowAddress) |
| 95 | +{ |
| 96 | + *((volatile unsigned int*)&(dev->waySelection)) = way; |
| 97 | + *((volatile unsigned int*)&(dev->rowAddress)) = rowAddress; |
| 98 | + *((volatile unsigned int*)&(dev->cmdSelect)) = V2FCommand_ReadPageTrigger; |
| 99 | +} |
| 100 | + |
| 101 | +void __attribute__((optimize("O0"))) V2FReadPageTransferAsync(V2FMCRegisters* dev, int way, void* pageDataBuffer, void* spareDataBuffer, unsigned int* errorInformation, unsigned int* completion, unsigned int rowAddress) |
| 102 | +{ |
| 103 | + *((volatile unsigned int*)&(dev->waySelection)) = way; |
| 104 | + *((volatile unsigned int*)&(dev->dataAddress)) = (unsigned int)pageDataBuffer; |
| 105 | + *((volatile unsigned int*)&(dev->spareAddress)) = (unsigned int)spareDataBuffer; |
| 106 | + *((volatile unsigned int*)&(dev->errorCountAddress)) = (unsigned int)errorInformation; |
| 107 | + *((volatile unsigned int*)&(dev->completionAddress)) = (unsigned int)completion; |
| 108 | + *((volatile unsigned int*)&(dev->rowAddress)) = rowAddress; |
| 109 | + *completion = 0; |
| 110 | + *((volatile unsigned int*)&(dev->cmdSelect)) = V2FCommand_ReadPageTransfer; |
| 111 | +} |
| 112 | + |
| 113 | +void __attribute__((optimize("O0"))) V2FReadPageTransferRawAsync(V2FMCRegisters* dev, int way, void* pageDataBuffer, unsigned int* completion) |
| 114 | +{ |
| 115 | + *((volatile unsigned int*)&(dev->waySelection)) = way; |
| 116 | + *((volatile unsigned int*)&(dev->dataAddress)) = (unsigned int)pageDataBuffer; |
| 117 | + *((volatile unsigned int*)&(dev->completionAddress)) = (unsigned int)completion; |
| 118 | + *completion = 0; |
| 119 | + *((volatile unsigned int*)&(dev->cmdSelect)) = V2FCommand_ReadPageTransferRaw; |
| 120 | +} |
| 121 | + |
| 122 | + |
| 123 | +void __attribute__((optimize("O0"))) V2FProgramPageAsync(V2FMCRegisters* dev, int way, unsigned int rowAddress, void* pageDataBuffer, void* spareDataBuffer) |
| 124 | +{ |
| 125 | + *((volatile unsigned int*)&(dev->waySelection)) = way; |
| 126 | + *((volatile unsigned int*)&(dev->rowAddress)) = rowAddress; |
| 127 | + *((volatile unsigned int*)&(dev->dataAddress)) = (unsigned int)pageDataBuffer; |
| 128 | + *((volatile unsigned int*)&(dev->spareAddress)) = (unsigned int)spareDataBuffer; |
| 129 | + *((volatile unsigned int*)&(dev->cmdSelect)) = V2FCommand_ProgramPage; |
| 130 | +} |
| 131 | + |
| 132 | +void __attribute__((optimize("O0"))) V2FEraseBlockAsync(V2FMCRegisters* dev, int way, unsigned int rowAddress) |
| 133 | +{ |
| 134 | + *((volatile unsigned int*)&(dev->waySelection)) = way; |
| 135 | + *((volatile unsigned int*)&(dev->rowAddress)) = rowAddress; |
| 136 | + *((volatile unsigned int*)&(dev->cmdSelect)) = V2FCommand_BlockErase; |
| 137 | +} |
| 138 | + |
| 139 | +void __attribute__((optimize("O0"))) V2FStatusCheckAsync(V2FMCRegisters* dev, int way, unsigned int* statusReport) |
| 140 | +{ |
| 141 | + *((volatile unsigned int*)&(dev->waySelection)) = way; |
| 142 | + *((volatile unsigned int*)&(dev->completionAddress)) = (unsigned int)statusReport; |
| 143 | + *statusReport = 0; |
| 144 | + *((volatile unsigned int*)&(dev->cmdSelect)) = V2FCommand_StatusCheck; |
| 145 | +} |
| 146 | + |
| 147 | +unsigned int __attribute__((optimize("O0"))) V2FStatusCheckSync(V2FMCRegisters* dev, int way) |
| 148 | +{ |
| 149 | + volatile unsigned int status; |
| 150 | + V2FStatusCheckAsync(dev, way, (unsigned int*)&status); |
| 151 | + while (!(status & 1)); |
| 152 | + return (status >> 1); |
| 153 | +} |
| 154 | + |
| 155 | +unsigned int __attribute__((optimize("O0"))) V2FReadyBusyAsync(V2FMCRegisters* dev) |
| 156 | +{ |
| 157 | + volatile unsigned int readyBusy = dev->readyBusy; |
| 158 | + |
| 159 | + return readyBusy; |
| 160 | +} |
| 161 | + |
| 162 | + |
0 commit comments