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