• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #ifndef MMC_CORE_H
10 #define MMC_CORE_H
11 
12 #include "hdf_base.h"
13 #include "hdf_device_desc.h"
14 #include "hdf_log.h"
15 #include "mmc_caps.h"
16 #include "mmc_protocol.h"
17 #include "osal_mem.h"
18 #include "osal_mutex.h"
19 #include "osal_time.h"
20 #include "platform_core.h"
21 
22 #ifdef __cplusplus
23 #if __cplusplus
24 extern "C" {
25 #endif
26 #endif /* __cplusplus */
27 
28 #define MMC_CNTLR_NR_MAX 3
29 #define MMC_DEV_NR_MAX   3
30 #define MMC_SEC_SIZE     512
31 
32 #define MMC_MIN(x, y) (((x) < (y)) ? (x) : (y))
33 #define MMC_MAX(x, y) (((x) < (y)) ? (y) : (x))
34 
35 struct MmcCntlr;
36 struct MmcCntlrOps;
37 struct MmcDevice;
38 struct MmcMsg;
39 struct MmcData;
40 struct MmcCmd;
41 enum MmcMsgCode;
42 enum MmcCmdCode;
43 union MmcDevState;
44 
45 enum MmcDevType {
46     MMC_DEV_EMMC = 0,
47     MMC_DEV_SD,
48     MMC_DEV_SDIO,
49     MMC_DEV_COMBO,
50     MMC_DEV_INVALID
51 };
52 
53 struct MmcCntlr {
54     struct IDeviceIoService service;
55     struct HdfDeviceObject *hdfDevObj;
56     struct PlatformDevice device;
57     struct OsalMutex mutex;
58     struct OsalSem released;
59     uint32_t devType;
60     struct MmcDevice *curDev;
61     struct MmcCntlrOps *ops;
62     struct PlatformQueue *msgQueue;
63     uint16_t index;
64     uint16_t voltDef;
65     uint32_t vddBit;
66     uint32_t freqMin;
67     uint32_t freqMax;
68     uint32_t freqDef;
69     union MmcOcr ocrDef;
70     union MmcCaps caps;
71     union MmcCaps2 caps2;
72     uint32_t maxBlkNum;
73     uint32_t maxBlkSize;
74     uint32_t maxReqSize;
75     bool devPlugged;
76     bool detecting;
77     void *priv;
78 };
79 
80 struct MmcCntlrOps {
81     int32_t (*request)(struct MmcCntlr *cntlr, struct MmcCmd *cmd);
82     int32_t (*setClock)(struct MmcCntlr *cntlr, uint32_t clock);
83     int32_t (*setPowerMode)(struct MmcCntlr *cntlr, enum MmcPowerMode mode);
84     int32_t (*setBusWidth)(struct MmcCntlr *cntlr, enum MmcBusWidth width);
85     int32_t (*setBusTiming)(struct MmcCntlr *cntlr, enum MmcBusTiming timing);
86     int32_t (*setSdioIrq)(struct MmcCntlr *cntlr, bool enable);
87     int32_t (*hardwareReset)(struct MmcCntlr *cntlr);
88     int32_t (*systemInit)(struct MmcCntlr *cntlr);
89     int32_t (*setEnhanceStrobe)(struct MmcCntlr *cntlr, bool enable);
90     int32_t (*switchVoltage)(struct MmcCntlr *cntlr, enum MmcVolt volt);
91     bool (*devReadOnly)(struct MmcCntlr *cntlr);
92     bool (*devPlugged)(struct MmcCntlr *cntlr);
93     bool (*devBusy)(struct MmcCntlr *cntlr);
94     int32_t  (*tune)(struct MmcCntlr *cntlr, uint32_t cmdCode);
95     int32_t (*rescanSdioDev)(struct MmcCntlr *cntlr);
96 };
97 
98 /* controller management */
99 int32_t MmcCntlrAdd(struct MmcCntlr *cntlr, bool needQueue);
100 void MmcCntlrRemove(struct MmcCntlr *cntlr);
101 struct MmcDevice *MmcCntlrGetDevice(struct MmcCntlr *cntlr);
102 
MmcCntlrGet(struct MmcCntlr * cntlr)103 static inline struct MmcCntlr *MmcCntlrGet(struct MmcCntlr *cntlr)
104 {
105     if (cntlr != NULL && PlatformDeviceGet(&cntlr->device) == HDF_SUCCESS) {
106         return cntlr;
107     }
108     return NULL;
109 }
110 
MmcCntlrGetByNr(uint16_t number)111 static inline struct MmcCntlr *MmcCntlrGetByNr(uint16_t number)
112 {
113     struct PlatformDevice *device = PlatformManagerGetDeviceByNumber(PlatformManagerGet(PLATFORM_MODULE_MMC), number);
114 
115     if (device == NULL) {
116         return NULL;
117     }
118     return CONTAINER_OF(device, struct MmcCntlr, device);
119 }
120 
MmcCntlrPut(struct MmcCntlr * cntlr)121 static inline void MmcCntlrPut(struct MmcCntlr *cntlr)
122 {
123     if (cntlr != NULL) {
124         PlatformDevicePut(&cntlr->device);
125     }
126 }
127 
MmcCntlrDevPresent(struct MmcCntlr * cntlr)128 static inline bool MmcCntlrDevPresent(struct MmcCntlr *cntlr)
129 {
130     return (cntlr != NULL && cntlr->curDev != NULL);
131 }
132 
MmcCntlrLock(struct MmcCntlr * cntlr)133 static inline void MmcCntlrLock(struct MmcCntlr *cntlr)
134 {
135     if (cntlr != NULL) {
136         (void)OsalMutexLock(&cntlr->mutex);
137     }
138 }
139 
MmcCntlrUnlock(struct MmcCntlr * cntlr)140 static inline void MmcCntlrUnlock(struct MmcCntlr *cntlr)
141 {
142     if (cntlr != NULL) {
143         (void)OsalMutexUnlock(&cntlr->mutex);
144     }
145 }
146 
MmcMDelay(uint32_t ms)147 static inline void MmcMDelay(uint32_t ms)
148 {
149 #ifdef __LITEOS_M__
150     OsalMSleep(ms);
151 #else
152     OsalMDelay(ms);
153 #endif
154 }
155 
156 /* controller common bussiness */
157 int32_t MmcCntlrDoRequest(struct MmcCntlr *cntlr, struct MmcCmd *cmd);
158 int32_t MmcCntlrAddMsgToQueue(struct MmcCntlr *cntlr, struct MmcCmd *cmd, int32_t code, bool block);
159 int32_t MmcCntlrAddRequestMsgToQueue(struct MmcCntlr *cntlr, struct MmcCmd *cmd);
160 int32_t MmcCntlrAddDetectMsgToQueue(struct MmcCntlr *cntlr);
161 int32_t MmcCntlrAddPlugMsgToQueue(struct MmcCntlr *cntlr);
162 int32_t MmcCntlrAddSdioRescanMsgToQueue(struct MmcCntlr *cntlr);
163 int32_t MmcCntlrParse(struct MmcCntlr *cntlr, struct HdfDeviceObject *obj);
164 int32_t MmcCntlrCreatSdioIrqThread(struct MmcCntlr *cntlr);
165 void MmcCntlrDestroySdioIrqThread(struct MmcCntlr *cntlr);
166 void MmcCntlrNotifySdioIrqThread(struct MmcCntlr *cntlr);
167 
168 /* controller private bussiness */
169 void MmcCntlrSetClock(struct MmcCntlr *cntlr, uint32_t clock);
170 void MmcCntlrSetBusWidth(struct MmcCntlr *cntlr, enum MmcBusWidth width);
171 void MmcCntlrSetBusTiming(struct MmcCntlr *cntlr, enum MmcBusTiming timing);
172 void MmcCntlrSetEnhanceStrobe(struct MmcCntlr *cntlr, bool enable);
173 int32_t MmcCntlrSwitchVoltage(struct MmcCntlr *cntlr, enum MmcVolt voltage);
174 bool MmcCntlrDevReadOnly(struct MmcCntlr *cntlr);
175 bool MmcCntlrDevBusy(struct MmcCntlr *cntlr);
176 bool MmcCntlrDevPlugged(struct MmcCntlr *cntlr);
177 int32_t MmcCntlrTune(struct MmcCntlr *cntlr, uint32_t cmdCode);
178 void MmcCntlrSelectWorkVoltage(struct MmcCntlr *cntlr, union MmcOcr *ocr);
179 void MmcCntlrPowerUp(struct MmcCntlr *cntlr);
180 void MmcCntlrPowerOff(struct MmcCntlr *cntlr);
181 int32_t MmcCntlrAllocDev(struct MmcCntlr *cntlr, enum MmcDevType devType);
182 void MmcCntlrFreeDev(struct MmcCntlr *cntlr);
183 bool MmcCntlrSupportUhs(struct MmcCntlr *cntlr);
184 bool MmcCntlrSupportHighSpeed400EnhancedStrobe(struct MmcCntlr *cntlr);
185 bool MmcCntlrSupportHighSpeed400(struct MmcCntlr *cntlr);
186 bool MmcCntlrSupportHighSpeed200(struct MmcCntlr *cntlr);
187 bool MmcCntlrSdSupportCmd23(struct MmcCntlr *cntlr);
188 bool MmcCntlrEmmcSupportCmd23(struct MmcCntlr *cntlr);
189 
190 struct MmcDeviceWorkParam {
191     uint32_t clock;
192     enum MmcBusWidth width;
193     enum MmcBusTiming timing;
194 };
195 
196 struct MmcRegister {
197     union MmcOcr ocr;
198     uint32_t rca;
199     uint32_t rawCid[CID_LEN];
200     uint32_t rawCsd[CSD_LEN];
201     struct MmcCid cid;
202     struct MmcCsd csd;
203 };
204 
205 union MmcDevState {
206     uint32_t stateData;
207     struct StateBitsData {
208         uint32_t present : 1;
209         uint32_t readonly : 1;
210         uint32_t highSpeed : 1;
211         uint32_t blockAddr : 1;
212         uint32_t ddrMode : 1;
213         uint32_t highSpeedDdr : 1;
214         uint32_t uhs : 1;
215         uint32_t sdxc : 1;
216         uint32_t hs200 : 1;
217         uint32_t sleep : 1;
218         uint32_t removable : 1;
219         uint32_t blkszForByteMode : 1;
220         uint32_t hs400 : 1;
221         uint32_t hs400es : 1;
222         uint32_t reserverd : 17;
223     } bits;
224 };
225 
226 struct MmcDevice {
227     struct PlatformDevice device;
228     struct MmcCntlr *cntlr;
229     struct MmcRegister reg;
230     struct MmcDeviceWorkParam workPara;
231     union MmcDevState state;
232     enum MmcDevType type;
233     size_t secSize;   // by bytes
234     size_t capacity;  // by sectors
235     size_t eraseSize; // by sectors
236     struct MmcBlock *mb;
237     void *priv;
238 };
239 
240 /* device management */
241 int32_t MmcDeviceAdd(struct MmcDevice *mmc);
242 void MmcDeviceAddOps(struct MmcDevice *mmc, void *ops);
243 void MmcDeviceRemove(struct MmcDevice *mmc);
244 struct MmcDevice *MmcDeviceGet(struct MmcDevice *mmc);
245 void MmcDevicePut(struct MmcDevice *mmc);
246 
247 /* device business */
248 ssize_t MmcDeviceRead(struct MmcDevice *mmc, uint8_t *buf, size_t startSec, size_t nSec);
249 ssize_t MmcDeviceWrite(struct MmcDevice *mmc, uint8_t *buf, size_t startSec, size_t nSec);
250 ssize_t MmcDeviceErase(struct MmcDevice *mmc, size_t startSec, size_t nSec);
251 
MmcDeviceIsPresent(struct MmcDevice * mmc)252 static inline bool MmcDeviceIsPresent(struct MmcDevice *mmc)
253 {
254     return (mmc != NULL && mmc->state.bits.present);
255 }
256 
257 struct MmcCmd {
258     uint32_t cmdCode;
259     uint32_t argument;
260     uint32_t resp[MMC_CMD_RESP_SIZE];
261     uint32_t respType;
262     int32_t returnError;
263     struct MmcData *data;
264 };
265 
266 #define DATA_WRITE (0x1 << 0)
267 #define DATA_READ (0x1 << 1)
268 #define DATA_STREAM (0x1 << 2)
269 struct MmcData {
270     uint32_t blockSize; /* data block size, byte */
271     uint32_t blockNum;
272     int32_t returnError;
273     uint8_t *dataBuffer;
274     void *scatter;
275     uint32_t scatterLen;
276     uint32_t dataFlags;
277     struct MmcCmd stopCmd; /* stop command */
278     bool sendStopCmd;
279 };
280 
281 enum MmcMsgCode {
282     MMC_MSG_REQUEST,
283     MMC_MSG_PLUG,
284     MMC_MSG_UNPLUG,
285     MMC_MSG_SDIO_RESCAN,
286 };
287 
288 struct MmcMsg {
289     struct PlatformMsg msg;
290     struct MmcCmd *mmcCmd;
291     struct OsalSem sem;
292     bool block;
293 };
294 
295 struct MmcRwData {
296     uint8_t *buf;
297     bool writeFlag;
298     size_t startSector;
299     size_t sectors;
300 };
301 
302 int32_t MmcDoDetect(struct MmcCntlr *cntlr);
303 void MmcDeleteDev(struct MmcCntlr *cntlr);
304 int32_t MmcSendStatus(struct MmcCntlr *cntlr, uint32_t *status);
305 int32_t MmcStopTransmission(struct MmcCntlr *cntlr, bool writeFlag, uint32_t *stopStatus);
306 int32_t MmcSendTuning(struct MmcCntlr *cntlr, uint32_t cmdCode, bool sendStop);
307 int32_t MmcSendErase(struct MmcCntlr *cntlr, uint32_t startSec, uint32_t nSec);
308 void MmcSetupReadWriteBlocksCmd(struct MmcDevice *mmc, struct MmcCmd *cmd, struct MmcRwData *info);
309 int32_t MmcSendReadWriteBlocks(struct MmcCntlr *cntlr, struct MmcRwData *info);
310 int32_t SdioReinit(struct MmcCntlr *cntlr);
311 int32_t SdioReadCccrIoEnable(struct MmcCntlr *cntlr, uint8_t *val);
312 int32_t SdioCccrIntEnable(struct MmcCntlr *cntlr);
313 int32_t SdioCccrIntDisable(struct MmcCntlr *cntlr);
314 int32_t SdioCccrIoEnable(struct MmcCntlr *cntlr);
315 int32_t SdioCccrIoDisable(struct MmcCntlr *cntlr);
316 int32_t SdioReadCccrIntPending(struct MmcCntlr *cntlr, uint8_t *val);
317 int32_t SdioReadCccrIoReady(struct MmcCntlr *cntlr, uint8_t *val);
318 int32_t SdioSetFbrIoBlockSize(struct MmcCntlr *cntlr, uint32_t blkSize);
319 int32_t SdioReadWriteByte(struct MmcCntlr *cntlr, bool writeFlag,
320     uint32_t funcNum, uint32_t addr, uint8_t *data);
321 int32_t SdioReadWriteBlock(struct MmcCntlr *cntlr, struct SdioRwBlockInfo *info);
322 
323 #ifdef __cplusplus
324 #if __cplusplus
325 }
326 #endif
327 #endif /* __cplusplus */
328 
329 #endif /* MMC_CORE_H */
330