• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "proc_fs.h"
17 #include "mmc_corex.h"
18 #include "mmc_sd.h"
19 
20 #define MCI_PARENT       "mci"
21 #define MCI_STATS_PROC   "mci_info"
22 
23 #define CLOCK_UINT_MAX_NUM 4
24 #define HIMCI_HOST_NUM 3
25 
26 static struct ProcDirEntry *g_procMciDir = NULL;
27 
ProcGetMmcCardUnplugged(struct MmcCntlr * mmc)28 static bool ProcGetMmcCardUnplugged(struct MmcCntlr *mmc)
29 {
30     if (mmc->caps.bits.nonremovable == 0) {
31         /*
32          * removable, for sd cards only.
33          * slots for sd cards can detect if the card is plugged.
34          */
35         return (MmcCntlrDevPluged(mmc) == false);
36     } else {
37         /* slots for sdio or emmc can't detect if the card is plugged in hardware. */
38         return (mmc->curDev == NULL);
39     }
40 }
41 
ProcStatsCardPluggedPrint(struct MmcCntlr * mmc,struct SeqBuf * s)42 static int32_t ProcStatsCardPluggedPrint(struct MmcCntlr *mmc, struct SeqBuf *s)
43 {
44     int32_t status;
45 
46     if (ProcGetMmcCardUnplugged(mmc) == true) {
47         status = LosBufPrintf(s, ": unplugged_disconnected\n");
48         if (status != 0) {
49             return HDF_FAILURE;
50         }
51         return HDF_ERR_NOT_SUPPORT;
52     }
53 
54     status = LosBufPrintf(s, ": plugged");
55     if (status != 0) {
56         return HDF_FAILURE;
57     }
58     return HDF_SUCCESS;
59 }
60 
ProcStatsCardConnectedPrint(struct MmcDevice * card,struct SeqBuf * s)61 static int32_t ProcStatsCardConnectedPrint(struct MmcDevice *card, struct SeqBuf *s)
62 {
63     int32_t status;
64 
65     if ((card == NULL) || card->state.bits.present == 0) {
66         status = LosBufPrintf(s, "_disconnected\n");
67         return HDF_FAILURE;
68     }
69 
70     status = LosBufPrintf(s, "_connected\n");
71     if (status != 0) {
72         return HDF_FAILURE;
73     }
74     return HDF_SUCCESS;
75 }
76 
ProcGetCardType(enum MmcDevType type)77 static char *ProcGetCardType(enum MmcDevType type)
78 {
79     static char *cardTypeStr[MMC_DEV_INVALID + 1] = {
80         "EMMC card",
81         "SD card",
82         "SDIO card",
83         "SD combo (IO+mem) card",
84         "unknown"
85     };
86 
87     if (type >= MMC_DEV_INVALID) {
88         return cardTypeStr[MMC_DEV_INVALID];
89     } else {
90         return cardTypeStr[type];
91     }
92 }
93 
ProcStatsCardTypePrint(struct MmcDevice * card,struct SeqBuf * s)94 static int32_t ProcStatsCardTypePrint(struct MmcDevice *card, struct SeqBuf *s)
95 {
96     int32_t status;
97     const char *type = NULL;
98 
99     status = LosBufPrintf(s, "\tType: %s", ProcGetCardType(card->type));
100     if (status != 0) {
101         return HDF_FAILURE;
102     }
103     if (card->state.bits.blockAddr > 0) {
104         type = "SDHC";
105         if (card->state.bits.sdxc > 0) {
106             type = "SDXC";
107         }
108         status = LosBufPrintf(s, "(%s)\n", type);
109         if (status != HDF_SUCCESS) {
110             return HDF_FAILURE;
111         }
112     } else {
113         status = LosBufPrintf(s, "\n");
114         if (status != HDF_SUCCESS) {
115             return HDF_FAILURE;
116         }
117     }
118     return HDF_SUCCESS;
119 }
120 
ProcAnalyzeClockScale(uint32_t clock,uint32_t * val)121 static uint32_t ProcAnalyzeClockScale(uint32_t clock, uint32_t *val)
122 {
123     uint32_t scale = 0;
124     uint32_t tmp = clock;
125 
126     *val = tmp;
127     while (tmp > 0) {
128         tmp = tmp / 1000;
129         if (tmp > 0 && scale < (CLOCK_UINT_MAX_NUM - 1)) {
130             *val = tmp;
131             scale++;
132         }
133     }
134     return scale;
135 }
136 
ProcStatsUhsPrint(struct MmcDevice * card,struct SeqBuf * s)137 static int32_t ProcStatsUhsPrint(struct MmcDevice *card, struct SeqBuf *s)
138 {
139     int32_t status;
140     struct SdDevice *dev = (struct SdDevice *)card;
141     const char *busSpeedMode = "";
142     static char *speedsOfUHS[] = {
143         "SDR12 ", "SDR25 ", "SDR50 ", "SDR104 ", "DDR50 "
144     };
145 
146     if (card->type == MMC_DEV_SD || card->type == MMC_DEV_COMBO) {
147         if (card->state.bits.uhs > 0 &&
148             dev->busSpeedMode < (sizeof(speedsOfUHS) / sizeof(speedsOfUHS[0]))) {
149             busSpeedMode = speedsOfUHS[dev->busSpeedMode];
150         }
151     }
152     status = LosBufPrintf(s, "\tMode: %s%s%s%s\n",
153         (card->state.bits.uhs > 0) ? "UHS " : ((card->state.bits.highSpeed > 0) ? "HS " : ""),
154         (card->state.bits.hs200 > 0) ? "HS200 " :
155         ((card->state.bits.hs400 > 0 || card->state.bits.hs400es > 0) ? "HS400 " : ""),
156         (card->state.bits.ddrMode > 0) ? "DDR" : "",
157         busSpeedMode);
158     if (status != 0) {
159         return HDF_FAILURE;
160     }
161 
162     return HDF_SUCCESS;
163 }
164 
ProcStatsSpeedPrint(struct MmcDevice * card,struct SeqBuf * s)165 static int32_t ProcStatsSpeedPrint(struct MmcDevice *card, struct SeqBuf *s)
166 {
167     int32_t status;
168     uint32_t speedClass = 0;
169     uint32_t uhsSpeedGrade = 0;
170     static char *speed = NULL;
171     struct SdDevice *dev = (struct SdDevice *)card;
172 
173     if (card->type == MMC_DEV_SD || card->type == MMC_DEV_COMBO) {
174         speedClass = dev->reg.ssr.speedClass;
175         uhsSpeedGrade = dev->reg.ssr.uhsSpeedGrade;
176     }
177 
178     if (speedClass > SD_SSR_SPEED_CLASS_4) {
179         status = LosBufPrintf(s, "\tSpeed Class: Class Reserved\n");
180     } else {
181         if (speedClass == SD_SSR_SPEED_CLASS_4) {
182             speedClass = SD_SSR_SPEED_CLASS_4_VAL;
183         } else {
184             speedClass *= (SD_SSR_SPEED_CLASS_1_VAL / SD_SSR_SPEED_CLASS_1);
185         }
186         status = LosBufPrintf(s, "\tSpeed Class: Class %d\n", speedClass);
187     }
188     if (status != 0) {
189         return HDF_FAILURE;
190     }
191 
192     if (uhsSpeedGrade == SD_SSR_UHS_SPEED_GRADE_0) {
193         speed = "Less than 10MB/sec(0h)";
194     } else if (uhsSpeedGrade == SD_SSR_UHS_SPEED_GRADE_1) {
195         speed = "10MB/sec and above(1h)";
196     } else if (uhsSpeedGrade == SD_SSR_UHS_SPEED_GRADE_3) {
197         speed = "30MB/sec and above(3h)";
198     } else {
199         speed = "Reserved";
200     }
201     status = LosBufPrintf(s, "\tUhs Speed Grade: %s\n", speed);
202     if (status != 0) {
203         return HDF_FAILURE;
204     }
205     return HDF_SUCCESS;
206 }
207 
ProcStatsClkPrint(uint32_t clock,struct SeqBuf * s)208 static int32_t ProcStatsClkPrint(uint32_t clock, struct SeqBuf *s)
209 {
210     int32_t status;
211     uint32_t clockScale;
212     uint32_t clockValue = 0;
213     static char *clockUnit[CLOCK_UINT_MAX_NUM] = {
214         "Hz",
215         "KHz",
216         "MHz",
217         "GHz"
218     };
219 
220     clockScale = ProcAnalyzeClockScale(clock, &clockValue);
221     status = LosBufPrintf(s, "\tHost work clock: %d%s\n", clockValue, clockUnit[clockScale]);
222     if (status != 0) {
223         return HDF_FAILURE;
224     }
225 
226     status = LosBufPrintf(s, "\tCard support clock: %d%s\n", clockValue, clockUnit[clockScale]);
227     if (status != 0) {
228         return HDF_FAILURE;
229     }
230 
231     status = LosBufPrintf(s, "\tCard work clock: %d%s\n", clockValue, clockUnit[clockScale]);
232     if (status != 0) {
233         return HDF_FAILURE;
234     }
235     return HDF_SUCCESS;
236 }
237 
ProcStatsCidPrint(struct MmcDevice * card,struct SeqBuf * s)238 static int32_t ProcStatsCidPrint(struct MmcDevice *card, struct SeqBuf *s)
239 {
240     int32_t status;
241 
242     status = LosBufPrintf(s, "\tCard cid: %08x%08x%08x%08x\n",
243         card->reg.rawCid[0], card->reg.rawCid[1], card->reg.rawCid[2], card->reg.rawCid[3]);
244     if (status != 0) {
245         return HDF_FAILURE;
246     }
247     return HDF_SUCCESS;
248 }
249 
ProcStatsCardInfoPrint(struct MmcCntlr * mmc,struct SeqBuf * s)250 static int32_t ProcStatsCardInfoPrint(struct MmcCntlr *mmc, struct SeqBuf *s)
251 {
252     struct MmcDevice *card = NULL;
253     int32_t status;
254 
255     status = ProcStatsCardPluggedPrint(mmc, s);
256     if (status != HDF_SUCCESS) {
257         if (status == HDF_ERR_NOT_SUPPORT) {
258             return HDF_SUCCESS;
259         }
260         return HDF_FAILURE;
261     }
262 
263     card = mmc->curDev;
264     if (card == NULL) {
265         return HDF_SUCCESS;
266     }
267     status = ProcStatsCardConnectedPrint(card, s);
268     if (status != HDF_SUCCESS) {
269         return status;
270     }
271     status = ProcStatsCardTypePrint(card, s);
272     if (status != HDF_SUCCESS) {
273         return status;
274     }
275     status = ProcStatsUhsPrint(card, s);
276     if (status != HDF_SUCCESS) {
277         return status;
278     }
279     status = ProcStatsSpeedPrint(card, s);
280     if (status != HDF_SUCCESS) {
281         return status;
282     }
283     status = ProcStatsClkPrint(card->workPara.clock, s);
284     if (status != HDF_SUCCESS) {
285         return status;
286     }
287     status = LosBufPrintf(s, "\tCard error count: 0\n");
288     if (status != 0) {
289         return HDF_FAILURE;
290     }
291     status = ProcStatsCidPrint(card, s);
292     if (status != HDF_SUCCESS) {
293         return HDF_FAILURE;
294     }
295     return HDF_SUCCESS;
296 }
297 
ProcStatsSeqPrint(struct SeqBuf * s)298 static int32_t ProcStatsSeqPrint(struct SeqBuf *s)
299 {
300     int32_t status;
301     uint32_t hostId;
302     struct MmcCntlr *mmc = NULL;
303 
304     for (hostId = 0; hostId < HIMCI_HOST_NUM; hostId++) {
305         mmc = MmcCntlrGetByNr(hostId);
306         if (mmc == NULL || mmc->priv == NULL) {
307             status = LosBufPrintf(s, "\nMCI%d: invalid\n", hostId);
308             if (status != 0) {
309                 return HDF_FAILURE;
310             }
311             continue;
312         }
313         status = LosBufPrintf(s, "\nMCI%d", hostId);
314         if (status != 0) {
315             return HDF_FAILURE;
316         }
317         status = ProcStatsCardInfoPrint(mmc, s);
318         if (status != 0) {
319             return HDF_FAILURE;
320         }
321     }
322     return HDF_SUCCESS;
323 }
324 
ProcMciShow(struct SeqBuf * m,void * v)325 static int32_t ProcMciShow(struct SeqBuf *m, void *v)
326 {
327     (void)v;
328     return ProcStatsSeqPrint(m);
329 }
330 
331 static const struct ProcFileOperations g_mciProcFops = {
332     .read = ProcMciShow,
333 };
334 
ProcMciInit(void)335 int32_t ProcMciInit(void)
336 {
337     struct ProcDirEntry *handle = NULL;
338 
339     g_procMciDir = ProcMkdir(MCI_PARENT, NULL);
340     if (g_procMciDir == NULL) {
341         HDF_LOGE("create directory error!");
342         return HDF_FAILURE;
343     }
344 
345     handle = CreateProcEntry(MCI_STATS_PROC, 0, (struct ProcDirEntry *)g_procMciDir);
346     if (handle == NULL) {
347         HDF_LOGE("create mount pointer error!");
348         return HDF_FAILURE;
349     }
350 
351     handle->procFileOps = &g_mciProcFops;
352     return HDF_SUCCESS;
353 }
354