• 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 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