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