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 devPluged;
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 (*setEnhanceSrobe)(struct MmcCntlr *cntlr, bool enable);
90 int32_t (*switchVoltage)(struct MmcCntlr *cntlr, enum MmcVolt volt);
91 bool (*devReadOnly)(struct MmcCntlr *cntlr);
92 bool (*devPluged)(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);
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
147 /* controller common bussiness */
148 int32_t MmcCntlrDoRequest(struct MmcCntlr *cntlr, struct MmcCmd *cmd);
149 int32_t MmcCntlrAddMsgToQueue(struct MmcCntlr *cntlr, struct MmcCmd *cmd, int32_t code, bool block);
150 int32_t MmcCntlrAddRequestMsgToQueue(struct MmcCntlr *cntlr, struct MmcCmd *cmd);
151 int32_t MmcCntlrAddDetectMsgToQueue(struct MmcCntlr *cntlr);
152 int32_t MmcCntlrAddPlugMsgToQueue(struct MmcCntlr *cntlr);
153 int32_t MmcCntlrAddSdioRescanMsgToQueue(struct MmcCntlr *cntlr);
154 int32_t MmcCntlrParse(struct MmcCntlr *cntlr, struct HdfDeviceObject *obj);
155 int32_t MmcCntlrCreatSdioIrqThread(struct MmcCntlr *cntlr);
156 void MmcCntlrDestroySdioIrqThread(struct MmcCntlr *cntlr);
157 void MmcCntlrNotifySdioIrqThread(struct MmcCntlr *cntlr);
158
159 /* controller private bussiness */
160 void MmcCntlrSetClock(struct MmcCntlr *cntlr, uint32_t clock);
161 void MmcCntlrSetBusWidth(struct MmcCntlr *cntlr, enum MmcBusWidth width);
162 void MmcCntlrSetBusTiming(struct MmcCntlr *cntlr, enum MmcBusTiming timing);
163 void MmcCntlrSetEnhanceSrobe(struct MmcCntlr *cntlr, bool enable);
164 int32_t MmcCntlrSwitchVoltage(struct MmcCntlr *cntlr, enum MmcVolt voltage);
165 bool MmcCntlrDevReadOnly(struct MmcCntlr *cntlr);
166 bool MmcCntlrDevBusy(struct MmcCntlr *cntlr);
167 bool MmcCntlrDevPluged(struct MmcCntlr *cntlr);
168 int32_t MmcCntlrTune(struct MmcCntlr *cntlr, uint32_t cmdCode);
169 void MmcCntlrSelectWorkVoltage(struct MmcCntlr *cntlr, union MmcOcr *ocr);
170 void MmcCntlrPowerUp(struct MmcCntlr *cntlr);
171 void MmcCntlrPowerOff(struct MmcCntlr *cntlr);
172 int32_t MmcCntlrAllocDev(struct MmcCntlr *cntlr, enum MmcDevType devType);
173 void MmcCntlrFreeDev(struct MmcCntlr *cntlr);
174 bool MmcCntlrSupportUhs(struct MmcCntlr *cntlr);
175 bool MmcCntlrSupportHighSpeed400EnhancedStrobe(struct MmcCntlr *cntlr);
176 bool MmcCntlrSupportHighSpeed400(struct MmcCntlr *cntlr);
177 bool MmcCntlrSupportHighSpeed200(struct MmcCntlr *cntlr);
178 bool MmcCntlrSdSupportCmd23(struct MmcCntlr *cntlr);
179 bool MmcCntlrEmmcSupportCmd23(struct MmcCntlr *cntlr);
180
181 struct MmcDeviceWorkParam {
182 uint32_t clock;
183 enum MmcBusWidth width;
184 enum MmcBusTiming timing;
185 };
186
187 struct MmcRegister {
188 union MmcOcr ocr;
189 uint32_t rca;
190 uint32_t rawCid[CID_LEN];
191 uint32_t rawCsd[CSD_LEN];
192 struct MmcCid cid;
193 struct MmcCsd csd;
194 };
195
196 union MmcDevState {
197 uint32_t stateData;
198 struct StateBitsData {
199 uint32_t present : 1;
200 uint32_t readonly : 1;
201 uint32_t highSpeed : 1;
202 uint32_t blockAddr : 1;
203 uint32_t ddrMode : 1;
204 uint32_t highSpeedDdr : 1;
205 uint32_t uhs : 1;
206 uint32_t sdxc : 1;
207 uint32_t hs200 : 1;
208 uint32_t sleep : 1;
209 uint32_t removeable : 1;
210 uint32_t blkszForByteMode : 1;
211 uint32_t hs400 : 1;
212 uint32_t hs400es : 1;
213 uint32_t reserverd : 17;
214 } bits;
215 };
216
217 struct MmcDevice {
218 struct PlatformDevice device;
219 struct MmcCntlr *cntlr;
220 struct MmcRegister reg;
221 struct MmcDeviceWorkParam workPara;
222 union MmcDevState state;
223 enum MmcDevType type;
224 size_t secSize; // by bytes
225 size_t capacity; // by sectors
226 size_t eraseSize; // by sectors
227 struct MmcBlock *mb;
228 void *priv;
229 };
230
231 /* device management */
232 int32_t MmcDeviceAdd(struct MmcDevice *mmc);
233 void MmcDeviceAddOps(struct MmcDevice *mmc, void *ops);
234 void MmcDeviceRemove(struct MmcDevice *mmc);
235 struct MmcDevice *MmcDeviceGet(struct MmcDevice *mmc);
236 void MmcDevicePut(struct MmcDevice *mmc);
237
238 /* device business */
239 ssize_t MmcDeviceRead(struct MmcDevice *mmc, uint8_t *buf, size_t startSec, size_t nSec);
240 ssize_t MmcDeviceWrite(struct MmcDevice *mmc, uint8_t *buf, size_t startSec, size_t nSec);
241 ssize_t MmcDeviceErase(struct MmcDevice *mmc, size_t startSec, size_t nSec);
242
MmcDeviceIsPresent(struct MmcDevice * mmc)243 static inline bool MmcDeviceIsPresent(struct MmcDevice *mmc)
244 {
245 return (mmc != NULL && mmc->state.bits.present);
246 }
247
248 struct MmcCmd {
249 uint32_t cmdCode;
250 uint32_t argument;
251 uint32_t resp[MMC_CMD_RESP_SIZE];
252 uint32_t respType;
253 int32_t returnError;
254 struct MmcData *data;
255 };
256
257 #define DATA_WRITE (0x1 << 0)
258 #define DATA_READ (0x1 << 1)
259 #define DATA_STREAM (0x1 << 2)
260 struct MmcData {
261 uint32_t blockSize; /* data block size, byte */
262 uint32_t blockNum;
263 int32_t returnError;
264 uint8_t *dataBuffer;
265 void *scatter;
266 uint32_t scatterLen;
267 uint32_t dataFlags;
268 struct MmcCmd stopCmd; /* stop command */
269 bool sendStopCmd;
270 };
271
272 enum MmcMsgCode {
273 MMC_MSG_REQUEST,
274 MMC_MSG_PLUG,
275 MMC_MSG_UNPLUG,
276 MMC_MSG_SDIO_RESCAN,
277 };
278
279 struct MmcMsg {
280 struct PlatformMsg msg;
281 struct MmcCmd *mmcCmd;
282 struct OsalSem sem;
283 bool block;
284 };
285
286 struct MmcRwData {
287 uint8_t *buf;
288 bool writeFlag;
289 size_t startSector;
290 size_t sectors;
291 };
292
293 int32_t MmcDoDetect(struct MmcCntlr *cntlr);
294 void MmcDeleteDev(struct MmcCntlr *cntlr);
295 int32_t MmcSendStatus(struct MmcCntlr *cntlr, uint32_t *status);
296 int32_t MmcStopTransmission(struct MmcCntlr *cntlr, bool writeFlag, uint32_t *stopStatus);
297 int32_t MmcSendTuning(struct MmcCntlr *cntlr, uint32_t cmdCode, bool sendStop);
298 int32_t MmcSendErase(struct MmcCntlr *cntlr, uint32_t startSec, uint32_t nSec);
299 void MmcSetupReadWriteBlocksCmd(struct MmcDevice *mmc, struct MmcCmd *cmd, struct MmcRwData *info);
300 int32_t MmcSendReadWriteBlocks(struct MmcCntlr *cntlr, struct MmcRwData *info);
301 int32_t SdioReinit(struct MmcCntlr *cntlr);
302 int32_t SdioReadCccrIoEnable(struct MmcCntlr *cntlr, uint8_t *val);
303 int32_t SdioCccrIntEnable(struct MmcCntlr *cntlr);
304 int32_t SdioCccrIntDisable(struct MmcCntlr *cntlr);
305 int32_t SdioCccrIoEnable(struct MmcCntlr *cntlr);
306 int32_t SdioCccrIoDisable(struct MmcCntlr *cntlr);
307 int32_t SdioReadCccrIntPending(struct MmcCntlr *cntlr, uint8_t *val);
308 int32_t SdioReadCccrIoReady(struct MmcCntlr *cntlr, uint8_t *val);
309 int32_t SdioSetFbrIoBlockSize(struct MmcCntlr *cntlr, uint32_t blkSize);
310 int32_t SdioReadWriteByte(struct MmcCntlr *cntlr, bool writeFlag,
311 uint32_t funcNum, uint32_t addr, uint8_t *data);
312 int32_t SdioReadWriteBlock(struct MmcCntlr *cntlr, struct SdioRwBlockInfo *info);
313
314 #ifdef __cplusplus
315 #if __cplusplus
316 }
317 #endif
318 #endif /* __cplusplus */
319
320 #endif /* MMC_CORE_H */
321