1 /*
2  * Copyright (c) 2016-2019, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <stdint.h>
34 #include <stdbool.h>
35 /*
36  * By default disable both asserts and log for this module.
37  * This must be done before DebugP.h is included.
38  */
39 #ifndef DebugP_ASSERT_ENABLED
40 #define DebugP_ASSERT_ENABLED 0
41 #endif
42 #ifndef DebugP_LOG_ENABLED
43 #define DebugP_LOG_ENABLED 0
44 #endif
45 
46 #include <ti/drivers/dpl/DebugP.h>
47 #include <ti/drivers/dpl/HwiP.h>
48 #include <ti/drivers/dpl/SemaphoreP.h>
49 #include <ti/drivers/Power.h>
50 #include <ti/drivers/power/PowerCC32XX.h>
51 #include <ti/drivers/sd/SDHostCC32XX.h>
52 #include <ti/drivers/dma/UDMACC32XX.h>
53 
54 /* Driverlib header files */
55 #include <ti/devices/cc32xx/inc/hw_common_reg.h>
56 #include <ti/devices/cc32xx/inc/hw_types.h>
57 #include <ti/devices/cc32xx/inc/hw_memmap.h>
58 #include <ti/devices/cc32xx/inc/hw_ocp_shared.h>
59 #include <ti/devices/cc32xx/inc/hw_ints.h>
60 #include <ti/devices/cc32xx/inc/hw_mmchs.h>
61 #include <ti/devices/cc32xx/inc/hw_udma.h>
62 #include <ti/devices/cc32xx/driverlib/rom.h>
63 #include <ti/devices/cc32xx/driverlib/rom_map.h>
64 #include <ti/devices/cc32xx/driverlib/pin.h>
65 #include <ti/devices/cc32xx/driverlib/prcm.h>
66 #include <ti/devices/cc32xx/driverlib/sdhost.h>
67 #include <ti/devices/cc32xx/driverlib/udma.h>
68 
69 #define PinConfigPinMode(config)       (((config) >> 8) & 0xF)
70 #define PinConfigPin(config)           (((config) >> 0) & 0x3F)
71 
72 #define PAD_CONFIG_BASE (OCP_SHARED_BASE + OCP_SHARED_O_GPIO_PAD_CONFIG_0)
73 #define PAD_RESET_STATE 0xC61
74 
75 /* Definitions for SDC driverlib commands  */
76 #define CMD_GO_IDLE_STATE    (SDHOST_CMD_0)
77 #define CMD_SEND_OP_COND     (SDHOST_CMD_1 | SDHOST_RESP_LEN_48)
78 #define CMD_ALL_SEND_CID     (SDHOST_CMD_2 | SDHOST_RESP_LEN_136)
79 #define CMD_SEND_REL_ADDR    (SDHOST_CMD_3 | SDHOST_RESP_LEN_48)
80 #define CMD_SELECT_CARD      (SDHOST_CMD_7 | SDHOST_RESP_LEN_48B)
81 #define CMD_DESELECT_CARD    (SDHOST_CMD_7)
82 #define CMD_SEND_IF_COND     (SDHOST_CMD_8 | SDHOST_RESP_LEN_48)
83 #define CMD_SEND_CSD         (SDHOST_CMD_9 | SDHOST_RESP_LEN_136)
84 #define CMD_STOP_TRANS       (SDHOST_CMD_12 | SDHOST_RESP_LEN_48B)
85 #define CMD_READ_SINGLE_BLK  (SDHOST_CMD_17 | SDHOST_RD_CMD | SDHOST_RESP_LEN_48)
86 #define CMD_READ_MULTI_BLK   (SDHOST_CMD_18 | SDHOST_RD_CMD | \
87                               SDHOST_RESP_LEN_48 | SDHOST_MULTI_BLK)
88 #define CMD_SET_BLK_CNT      (SDHOST_CMD_23 | SDHOST_RESP_LEN_48)
89 #define CMD_WRITE_SINGLE_BLK (SDHOST_CMD_24 | SDHOST_WR_CMD | SDHOST_RESP_LEN_48)
90 #define CMD_WRITE_MULTI_BLK  (SDHOST_CMD_25 | SDHOST_WR_CMD | \
91                               SDHOST_RESP_LEN_48 | SDHOST_MULTI_BLK)
92 #define CMD_SD_SEND_OP_COND  (SDHOST_CMD_41 | SDHOST_RESP_LEN_48)
93 #define CMD_APP_CMD          (SDHOST_CMD_55 | SDHOST_RESP_LEN_48)
94 
95 /* Group of all possible SD command and data error flags */
96 #define CMDERROR             (SDHOST_INT_CTO | SDHOST_INT_CEB)
97 
98 #define DATAERROR            (SDHOST_INT_DTO | SDHOST_INT_DCRC | \
99                               SDHOST_INT_DEB | SDHOST_INT_CERR | \
100                               SDHOST_INT_BADA)
101 
102 #define SECTORSIZE           (512)
103 
104 /* Voltage window (VDD) used on this device (3.3-3.6 V) */
105 #define VOLTAGEWINDOW        (0x00E00000)
106 
107 /* Bit set to indicate the host controller has high capacity support */
108 #define HIGHCAPSUPPORT       (0x40000000)
109 
110 /* Voltage supplied 2.7-3.6V */
111 #define SUPPLYVOLTAGE        (0x00000100)
112 
113 /* Checksum to validate SD command responses */
114 #define CHECKSUM             (0xA5)
115 
116 /* Setup the UDMA controller to either read or write to the SDHost buffer */
117 #define UDMAWRITE            (0x01)
118 
119 #define UDMAREAD             (0x00)
120 
121 /* Define used for commands that do not require an argument */
122 #define NULLARG              (0x00)
123 
124 /* SDHostCC32XX configuration - initialized in the board file */
125 extern const SD_Config SD_config[];
126 
127 /* SDHostCC32XX functions */
128 void SDHostCC32XX_close(SD_Handle handle);
129 int_fast16_t SDHostCC32XX_control(SD_Handle handle, uint_fast16_t cmd,
130     void *arg);
131 uint_fast32_t SDHostCC32XX_getNumSectors(SD_Handle handle);
132 uint_fast32_t SDHostCC32XX_getSectorSize(SD_Handle handle);
133 int_fast16_t SDHostCC32XX_initialize(SD_Handle handle);
134 void SDHostCC32XX_init(SD_Handle handle);
135 SD_Handle SDHostCC32XX_open(SD_Handle handle, SD_Params *params);
136 int_fast16_t SDHostCC32XX_read(SD_Handle handle, void *buf,
137     int_fast32_t sector, uint_fast32_t secCount);
138 int_fast16_t SDHostCC32XX_write(SD_Handle handle, const void *buf,
139     int_fast32_t sector, uint_fast32_t secCount);
140 
141 /* Local Functions */
142 static inline void configDMAChannel(SD_Handle handle, uint_fast32_t channelSel,
143     uint_fast32_t operation);
144 static int_fast32_t deSelectCard(SD_Handle handle);
145 static uint_fast32_t getPowerMgrId(uint_fast32_t baseAddr);
146 static void hwiIntFxn(uintptr_t handle);
147 static void initHw(SD_Handle handle);
148 static int postNotifyFxn(unsigned int eventType, uintptr_t eventArg,
149     uintptr_t clientArg);
150 static int_fast32_t send_cmd(SD_Handle handle, uint_fast32_t cmd,
151     uint_fast32_t arg);
152 static int_fast32_t selectCard(SD_Handle handle);
153 
154 /* SDHostCC32XX function table for SDSPICC32XX implementation */
155 const SD_FxnTable sdHostCC32XX_fxnTable = {
156     SDHostCC32XX_close,
157     SDHostCC32XX_control,
158     SDHostCC32XX_getNumSectors,
159     SDHostCC32XX_getSectorSize,
160     SDHostCC32XX_init,
161     SDHostCC32XX_initialize,
162     SDHostCC32XX_open,
163     SDHostCC32XX_read,
164     SDHostCC32XX_write
165 };
166 
167 /*
168  *  ======== SDHostCC32XX_close ========
169  */
SDHostCC32XX_close(SD_Handle handle)170 void SDHostCC32XX_close(SD_Handle handle)
171 {
172     SDHostCC32XX_Object          *object = handle->object;
173     SDHostCC32XX_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
174     uint32_t                      padRegister;
175 
176     if (object->cardType != SD_NOCARD) {
177         /* De-select the SD Card, move back to standby state */
178         if (deSelectCard(handle) != SD_STATUS_SUCCESS) {
179             DebugP_log1("SDHost:(%p) Failed to de-select SD Card",
180                 hwAttrs->baseAddr);
181         }
182     }
183 
184     /* Disable SD Host interrupts */
185     MAP_SDHostIntDisable(hwAttrs->baseAddr, DATAERROR | CMDERROR);
186 
187     if (object->dmaHandle) {
188         UDMACC32XX_close(object->dmaHandle);
189     }
190     if (object->cmdSem) {
191         SemaphoreP_delete(object->cmdSem);
192     }
193     if (object->hwiHandle) {
194         HwiP_delete(object->hwiHandle);
195     }
196 
197     /* Remove Power driver settings */
198     if (object->clkPin != (uint16_t)-1) {
199         PowerCC32XX_restoreParkState((PowerCC32XX_Pin)object->clkPin,
200             object->prevParkCLK);
201         object->clkPin = (uint16_t)-1;
202     }
203     Power_unregisterNotify(&object->postNotify);
204     Power_releaseDependency(object->powerMgrId);
205 
206     /* Restore pin pads to their reset states */
207     padRegister = (PinToPadGet((hwAttrs->dataPin) & 0x3f)<<2) + PAD_CONFIG_BASE;
208     HWREG(padRegister) = PAD_RESET_STATE;
209     padRegister = (PinToPadGet((hwAttrs->cmdPin) & 0x3f)<<2) + PAD_CONFIG_BASE;
210     HWREG(padRegister) = PAD_RESET_STATE;
211     padRegister = (PinToPadGet((hwAttrs->clkPin) & 0x3f)<<2) + PAD_CONFIG_BASE;
212     HWREG(padRegister) = PAD_RESET_STATE;
213 
214     object->isOpen = false;
215 
216     DebugP_log1("SDHost:(%p) closed and released power dependency",
217         hwAttrs->baseAddr);
218 }
219 
220 /*
221  *  ======== SDHostCC32XX_control ========
222  *  @pre    Function assumes that the handle is not NULL.
223  */
SDHostCC32XX_control(SD_Handle handle,uint_fast32_t cmd,void * arg)224 int_fast16_t SDHostCC32XX_control(SD_Handle handle, uint_fast32_t cmd,
225     void *arg)
226 {
227     /* No implementation yet */
228     return (SD_STATUS_UNDEFINEDCMD);
229 }
230 
231 /*
232  *  ======== SDHostCC32XX_getNumSectors ========
233  *  Function to read the CSD register of the SD card on the drive specified
234  *  by the SD_Handle and calculate the total card capacity in sectors.
235  */
SDHostCC32XX_getNumSectors(SD_Handle handle)236 uint_fast32_t SDHostCC32XX_getNumSectors(SD_Handle handle)
237 {
238     uint_fast32_t                 sectors = 0;
239     uint_fast32_t                 cSize; /* Device size */
240     uint_fast32_t                 blockSize; /* Read block length */
241     uint_fast32_t                 sizeMult;
242     uint_fast32_t                 resp[4];
243     SDHostCC32XX_Object          *object = handle->object;
244     SDHostCC32XX_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
245 
246     Power_setConstraint(PowerCC32XX_DISALLOW_LPDS);
247     DebugP_log1("SDHost:(%p) SDHostCC32XX_getNumSectors set command"
248         " power constraint", hwAttrs->baseAddr);
249 
250     /* De-Select the card on the input drive(Stand-by state) */
251     if (deSelectCard(handle) != SD_STATUS_SUCCESS) {
252         Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
253         DebugP_log1("SDHost:(%p) SDHostCC32XX_getNumSectors released command"
254             " power constraint", hwAttrs->baseAddr);
255         return (0);
256     }
257 
258     if (send_cmd(handle, CMD_SEND_CSD, (object->rca << 16)) ==
259         SD_STATUS_SUCCESS) {
260 
261         MAP_SDHostRespGet(hwAttrs->baseAddr, (unsigned long *)resp);
262 
263        /*
264         * 136 bit CSD register is read into an array of 4 words
265         * Note: Does not include 8 bit CRC
266         * resp[0] = CSD[31:0]
267         * resp[1] = CSD[63:32]
268         * resp[2] = CSD[95:64]
269         * resp[3] = CSD[127:96]
270         */
271         if(((resp[3] >> 30) & 0x01) == 1) {
272             sectors = (resp[1] >> 16 | ((resp[2] & 0x3F) << 16)) + 1;
273             sectors *= 1024;
274         }
275         else {
276             blockSize = 1 << ((resp[2] >> 16) & 0x0F);
277             sizeMult = ((resp[1] >> 15) & 0x07);
278             cSize = ((resp[1] >> 30) | (resp[2] & 0x3FF) << 2);
279             sectors = (cSize + 1) * (1 << (sizeMult + 2));
280             sectors = (sectors * blockSize) / SECTORSIZE;
281 
282         }
283     }
284 
285     /* Select the card on the input drive(Transfer state) */
286     if (selectCard(handle) != SD_STATUS_SUCCESS) {
287         sectors = 0;
288     }
289 
290     Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
291     DebugP_log1("SDHost:(%p) SDHostCC32XX_getNumSectors released command"
292         " power constraint", hwAttrs->baseAddr);
293 
294     return (sectors);
295 }
296 
297 /*
298  *  ======== SDHostCC32XX_getSectorSize ========
299  *  Function to perform a disk read from the SD Card on the specifed drive.
300  */
SDHostCC32XX_getSectorSize(SD_Handle handle)301 uint_fast32_t SDHostCC32XX_getSectorSize(SD_Handle handle)
302 {
303     return (SECTORSIZE);
304 }
305 
306 /*
307  *  ======== SDHostCC32XX_initialize ========
308  *  Function to initialize the SD Card.
309  */
SDHostCC32XX_initialize(SD_Handle handle)310 int_fast16_t SDHostCC32XX_initialize(SD_Handle handle)
311 {
312     int_fast32_t                  result;
313     uint_fast32_t                 resp[4];
314     SDHostCC32XX_Object          *object = handle->object;
315     SDHostCC32XX_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
316 
317     Power_setConstraint(PowerCC32XX_DISALLOW_LPDS);
318     DebugP_log1("SDHost:(%p) SDHostCC32XX_initialize set read/write"
319         " power constraint", hwAttrs->baseAddr);
320 
321     /* Send go to IDLE command */
322     result = send_cmd(handle, CMD_GO_IDLE_STATE, NULLARG);
323 
324     if (result == SD_STATUS_SUCCESS) {
325         /* Get interface operating condition for the card */
326         result = send_cmd(handle, CMD_SEND_IF_COND,
327             SUPPLYVOLTAGE | CHECKSUM);
328         /* Verify response will be valid */
329         if (result == SD_STATUS_SUCCESS) {
330             MAP_SDHostRespGet(hwAttrs->baseAddr, (unsigned long *)resp);
331         }
332     }
333 
334     /* SD ver 2.0 or higher card */
335     if ((result == SD_STATUS_SUCCESS) && ((resp[0] & 0xFF) ==
336         CHECKSUM)) {
337         object->cardType = SD_SDSC;
338 
339         /* Wait for card to be ready */
340         do {
341             /* Send ACMD41 */
342             result = send_cmd(handle, CMD_APP_CMD, NULLARG);
343 
344             if (result == SD_STATUS_SUCCESS) {
345                 result = send_cmd(handle, CMD_SD_SEND_OP_COND,
346                     HIGHCAPSUPPORT | VOLTAGEWINDOW);
347                 /* Response contains 32-bit OCR register */
348                 MAP_SDHostRespGet(hwAttrs->baseAddr, (unsigned long *)resp);
349             }
350 
351         /* Wait until card is ready, spool on busy bit */
352         } while((result == SD_STATUS_SUCCESS) && ((resp[0] >> 31) == 0));
353 
354         /* Card capacity status bit */
355         if ((result == SD_STATUS_SUCCESS) && (resp[0] & (1UL << 30))) {
356             object->cardType = SD_SDHC;
357         }
358     }
359     /* It's a MMC or SD 1.x card */
360     else {
361         /* Wait for card to be ready */
362         do {
363             /* Send ACMD41 */
364             result = send_cmd(handle, CMD_APP_CMD, NULLARG);
365 
366             if (result == SD_STATUS_SUCCESS) {
367                 result = send_cmd(handle, CMD_SD_SEND_OP_COND, VOLTAGEWINDOW);
368             }
369 
370             if (result == SD_STATUS_SUCCESS) {
371                 /* Response contains 32-bit OCR register */
372                 MAP_SDHostRespGet(hwAttrs->baseAddr, (unsigned long *)resp);
373             }
374 
375         /* Wait until card is ready, spool on busy bit */
376         } while((result == SD_STATUS_SUCCESS) && ((resp[0] >> 31) == 0));
377 
378         if (result == SD_STATUS_SUCCESS) {
379             object->cardType = SD_SDSC;
380         }
381         else if (send_cmd(handle, CMD_SEND_OP_COND, NULLARG) ==
382             SD_STATUS_SUCCESS) {
383             object->cardType = SD_MMC;
384         }
385         /* No command responses */
386         else {
387             object->cardType = SD_NOCARD;
388         }
389     }
390 
391     /* Get the relative card address (RCA) of the attached card */
392     if (object->cardType != SD_NOCARD) {
393         result = send_cmd(handle, CMD_ALL_SEND_CID, NULLARG);
394 
395         if (result == SD_STATUS_SUCCESS) {
396             result = send_cmd(handle, CMD_SEND_REL_ADDR, NULLARG);
397         }
398 
399         if (result == SD_STATUS_SUCCESS) {
400             /* Fill in the RCA */
401             MAP_SDHostRespGet(hwAttrs->baseAddr, (unsigned long *)resp);
402 
403             object->rca = resp[0] >> 16;
404 
405             /* Select the card on the input drive(Transfer state) */
406             result = selectCard(handle);
407             if (result == SD_STATUS_SUCCESS) {
408                 /* Set card read/write block length */
409                 MAP_SDHostBlockSizeSet(hwAttrs->baseAddr, SECTORSIZE);
410 
411                 /* Initialization succeeded */
412                 result = SD_STATUS_SUCCESS;
413             }
414         }
415     }
416     else {
417         DebugP_log1("SDHost:(%p) Could not select card",
418             hwAttrs->baseAddr);
419         result = SD_STATUS_ERROR;
420     }
421 
422     Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
423     DebugP_log1("SDHost:(%p) SDHostCC32XX_initialize released read/write"
424         " power constraint", hwAttrs->baseAddr);
425 
426     return (result);
427 }
428 
429 /*
430  *  ======== SDHostCC32XX_init ========
431  *  Function to initialize the SDHost module
432  */
SDHostCC32XX_init(SD_Handle handle)433 void SDHostCC32XX_init(SD_Handle handle)
434 {
435     SDHostCC32XX_Object *object = handle->object;
436 
437     object->buffer = NULL;
438     object->sectorCount = 0;
439     object->cardType = SD_NOCARD;
440     object->isOpen = false;
441 
442     UDMACC32XX_init();
443 }
444 
445 /*
446  *  ======== SDHostCC32XX_open ========
447  */
SDHostCC32XX_open(SD_Handle handle,SD_Params * params)448 SD_Handle SDHostCC32XX_open(SD_Handle handle, SD_Params *params)
449 {
450     uintptr_t                     key;
451     SemaphoreP_Params             semParams;
452     HwiP_Params                   hwiParams;
453     SDHostCC32XX_Object          *object = handle->object;
454     SDHostCC32XX_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
455     uint16_t pin;
456 
457     key = HwiP_disable();
458 
459     if (object->isOpen) {
460         HwiP_restore(key);
461 
462         DebugP_log1("SDHost:(%p) already in use.", hwAttrs->baseAddr);
463         return (NULL);
464     }
465     object->isOpen = true;
466 
467     HwiP_restore(key);
468 
469     /* Initialize the SDCARD_CLK pin ID to undefined */
470     object->clkPin = (uint16_t)-1;
471 
472     /* Get the Power resource Id from the base address */
473     object->powerMgrId = getPowerMgrId(hwAttrs->baseAddr);
474     if (object->powerMgrId == (unsigned int)-1) {
475         DebugP_log1("SDHost:(%p) Failed to determine Power resource id",
476             hwAttrs->baseAddr);
477         return (NULL);
478     }
479 
480     /*
481      *  Register power dependency. Keeps the clock running in SLP
482      *  and DSLP modes.
483      */
484     Power_setDependency(object->powerMgrId);
485 
486     Power_registerNotify(&object->postNotify, PowerCC32XX_AWAKE_LPDS,
487         postNotifyFxn, (uintptr_t)handle);
488 
489     object->dmaHandle = UDMACC32XX_open();
490     if (object->dmaHandle == NULL) {
491         DebugP_log1("SDHost:(%p) UDMACC32XX_open() failed.",
492             hwAttrs->baseAddr);
493         SDHostCC32XX_close(handle);
494         return (NULL);
495     }
496 
497     SemaphoreP_Params_init(&semParams);
498     semParams.mode = SemaphoreP_Mode_COUNTING;
499     object->cmdSem = SemaphoreP_create(0, &semParams);
500 
501     if (object->cmdSem == NULL) {
502         DebugP_log1("SDHost:(%p) SemaphoreP_create() failed.",
503             hwAttrs->baseAddr);
504         SDHostCC32XX_close(handle);
505         return (NULL);
506     }
507 
508     HwiP_Params_init(&hwiParams);
509     hwiParams.arg = (uintptr_t)handle;
510     hwiParams.priority = hwAttrs->intPriority;
511     object->hwiHandle = HwiP_create(INT_MMCHS, hwiIntFxn,
512         &hwiParams);
513     if (object->hwiHandle == NULL) {
514         DebugP_log1("SDHostT:(%p) HwiP_create() failed", hwAttrs->baseAddr);
515         SDHostCC32XX_close(handle);
516         return (NULL);
517     }
518 
519     /* Initialize the hardware */
520     initHw(handle);
521 
522     /* Save clkPin park state; set to logic '0' during LPDS */
523     pin = PinConfigPin(hwAttrs->clkPin);
524     object->prevParkCLK =
525         (PowerCC32XX_ParkState) PowerCC32XX_getParkState((PowerCC32XX_Pin)pin);
526     PowerCC32XX_setParkState((PowerCC32XX_Pin)pin, 0);
527     object->clkPin = pin;
528 
529     DebugP_log1("SDHost:(%p) opened", hwAttrs->baseAddr);
530 
531     return (handle);
532 }
533 
534 /*
535  *  ======== SDHostCC32XX_read ========
536  */
SDHostCC32XX_read(SD_Handle handle,void * buf,int_fast32_t sector,uint_fast32_t secCount)537 int_fast16_t SDHostCC32XX_read(SD_Handle handle, void *buf,
538     int_fast32_t sector, uint_fast32_t secCount)
539 {
540     int_fast32_t                  result;
541     uint_fast32_t                 ret;
542     uint_fast32_t                 size;
543     SDHostCC32XX_Object          *object  = handle->object;
544     SDHostCC32XX_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
545 
546     object->stat = SD_STATUS_SUCCESS;
547 
548     /* Check for valid sector count */
549     if (secCount == 0) {
550         return (SD_STATUS_ERROR);
551     }
552 
553     /* SDSC uses linear address, SDHC uses block address */
554     if (object->cardType == SD_SDSC) {
555         sector = sector * SECTORSIZE;
556     }
557 
558     Power_setConstraint(PowerCC32XX_DISALLOW_LPDS);
559 
560     /* Set the block count */
561     MAP_SDHostBlockCountSet(hwAttrs->baseAddr, secCount);
562 
563     /* If input buffer is word aligned use DMA */
564     if (!(((uint32_t)buf) & 0x03)) {
565         object->buffer = (uint32_t *)buf;
566         object->sectorCount = secCount;
567 
568         /* Configure ping */
569         configDMAChannel(handle, UDMA_PRI_SELECT , UDMAREAD);
570 
571         /* Add offset to input buffer */
572         object->buffer = object->buffer + (SECTORSIZE / 4);
573 
574         /* Configure pong */
575         if (secCount > 1) {
576             configDMAChannel(handle, UDMA_ALT_SELECT , UDMAREAD);
577         }
578 
579         /*
580          * Enable DMA and transmit complete interrupts, reset ping and
581          * dmaPosted flags.
582          */
583         object->dmaPosted = false;
584         object->ping = false;
585         MAP_SDHostIntEnable(hwAttrs->baseAddr, SDHOST_INT_DMARD | SDHOST_INT_TC);
586 
587         /* Send multi block read command to the SD card */
588         result = send_cmd(handle, CMD_READ_MULTI_BLK | SDHOST_DMA_EN, sector);
589 
590         /* Wait for DMA read(s) to complete */
591         if (result == SD_STATUS_SUCCESS) {
592             /* Any remaining DMA transfers are completed in the hwiFxn */
593             SemaphoreP_pend(object->cmdSem, SemaphoreP_WAIT_FOREVER);
594         }
595     }
596     /* Poll buffer for new data */
597     else {
598         /* Compute the number of words to read */
599         size = (SECTORSIZE * secCount) / 4;
600 
601         /* Send multi block read command */
602         result = send_cmd(handle, CMD_READ_MULTI_BLK, sector);
603 
604         if (result == SD_STATUS_SUCCESS) {
605             /* Read single word of data */
606             while (size > 0) {
607                 ret = MAP_SDHostDataNonBlockingRead(hwAttrs->baseAddr,
608                     (unsigned long *)buf);
609                 /* Block until buffer is ready */
610                 if (ret == 0) {
611                     MAP_SDHostIntEnable(hwAttrs->baseAddr, SDHOST_INT_BRR);
612 
613                     SemaphoreP_pend(object->cmdSem, SemaphoreP_WAIT_FOREVER);
614 
615                     MAP_SDHostIntDisable(hwAttrs->baseAddr, SDHOST_INT_BRR);
616                 }
617                 else {
618                     buf = (uint_least8_t *)buf + 4;
619                     size--;
620                 }
621             }
622         }
623     }
624 
625     /* Verify host controller errors didn't occur */
626     if (object->stat == SD_STATUS_SUCCESS) {
627 
628         MAP_SDHostIntEnable(hwAttrs->baseAddr, SDHOST_INT_TC);
629 
630         /* Wait for full data transfer to complete */
631         SemaphoreP_pend(object->cmdSem, SemaphoreP_WAIT_FOREVER);
632 
633         MAP_SDHostIntDisable(hwAttrs->baseAddr, SDHOST_INT_TC);
634     }
635 
636     /* Verify host controller errors didn't occur */
637     if (object->stat == SD_STATUS_SUCCESS) {
638 
639         /* Wait for command transfer stop acknowledgement */
640         result = send_cmd(handle, CMD_STOP_TRANS, NULLARG);
641 
642         if (result ==  SD_STATUS_SUCCESS) {
643             MAP_SDHostIntEnable(hwAttrs->baseAddr, SDHOST_INT_TC);
644 
645             SemaphoreP_pend(object->cmdSem, SemaphoreP_WAIT_FOREVER);
646 
647             MAP_SDHostIntDisable(hwAttrs->baseAddr, SDHOST_INT_TC);
648         }
649     }
650 
651     if (object->stat != SD_STATUS_SUCCESS) {
652         result = SD_STATUS_ERROR;
653     }
654 
655     Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
656     DebugP_log1("SDHost:(%p) SDHostCC32XX_read released read power"
657         " constraint", hwAttrs->baseAddr);
658 
659     return (result);
660 }
661 
662 /*
663  *  ======== SDHostCC32XX_write ========
664  */
SDHostCC32XX_write(SD_Handle handle,const void * buf,int_fast32_t sector,uint_fast32_t secCount)665 int_fast16_t SDHostCC32XX_write(SD_Handle handle, const void *buf,
666     int_fast32_t sector, uint_fast32_t secCount)
667 {
668     int_fast32_t                  result;
669     uint_fast32_t                 ret;
670     uint_fast32_t                 size;
671     SDHostCC32XX_Object          *object  = handle->object;
672     SDHostCC32XX_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
673 
674     object->stat = SD_STATUS_SUCCESS;
675 
676     /* Check for valid sector count */
677     if (secCount == 0) {
678         return (SD_STATUS_ERROR);
679     }
680 
681     /* SDSC uses linear address, SDHC uses block address */
682     if(object->cardType == SD_SDSC) {
683         sector = sector * SECTORSIZE;
684     }
685 
686     Power_setConstraint(PowerCC32XX_DISALLOW_LPDS);
687 
688     /* Set the block count */
689     MAP_SDHostBlockCountSet(hwAttrs->baseAddr, secCount);
690 
691     /* Set card write block erase count */
692     result = send_cmd(handle, CMD_APP_CMD,  object->rca << 16);
693     if (result != SD_STATUS_SUCCESS) {
694         return (SD_STATUS_ERROR);
695     }
696     result = send_cmd(handle, CMD_SET_BLK_CNT, secCount);
697     if (result != SD_STATUS_SUCCESS) {
698         return (SD_STATUS_ERROR);
699     }
700 
701     /* If the write buffer is word aligned use the DMA */
702     if (!(((uint_fast32_t)buf) & 0x03)) {
703         object->buffer = (uint32_t *)buf;
704         object->sectorCount = secCount;
705 
706         /* Configure ping */
707         configDMAChannel(handle, UDMA_PRI_SELECT, UDMAWRITE);
708 
709         /* Add offset to input buffer */
710         object->buffer = object->buffer + (SECTORSIZE / 4);
711 
712         /* Configure pong */
713         if (secCount > 1) {
714             configDMAChannel(handle, UDMA_ALT_SELECT, UDMAWRITE);
715         }
716 
717         /*
718          * Enable DMA and transmit complete interrupts, reset ping and
719          * dmaPosted flags.
720          */
721         object->dmaPosted = false;
722         object->ping = false;
723         MAP_SDHostIntEnable(hwAttrs->baseAddr, SDHOST_INT_DMAWR | SDHOST_INT_TC);
724 
725         /* Send write multi block command to the SD card */
726         result = send_cmd(handle, CMD_WRITE_MULTI_BLK | SDHOST_DMA_EN, sector);
727 
728         /* Wait for the DMA to finish */
729         if (result == SD_STATUS_SUCCESS) {
730             /* Any remaining DMA transfers are completed in the hwiFxn */
731             SemaphoreP_pend(object->cmdSem, SemaphoreP_WAIT_FOREVER);
732         }
733     }
734     else {
735         /* Compute the number of words to write */
736         size = (SECTORSIZE * secCount) / 4;
737 
738         /* Verify that the block count had been previous set */
739         if (result == SD_STATUS_SUCCESS) {
740             result = send_cmd(handle, CMD_WRITE_MULTI_BLK, sector);
741         }
742 
743         if (result == SD_STATUS_SUCCESS) {
744             /* Write single word of data */
745             while (size > 0) {
746                 ret = MAP_SDHostDataNonBlockingWrite(hwAttrs->baseAddr,
747                     (*(unsigned long *)buf));
748 
749                 /* Block until buffer is ready */
750                 if (ret == 0) {
751                     MAP_SDHostIntEnable(hwAttrs->baseAddr, SDHOST_INT_BWR);
752 
753                     SemaphoreP_pend(object->cmdSem, SemaphoreP_WAIT_FOREVER);
754 
755                     MAP_SDHostIntDisable(hwAttrs->baseAddr, SDHOST_INT_BWR);
756 
757                 }
758                 else {
759                     buf = (uint_least8_t *)buf + 4;
760                     size--;
761                 }
762             }
763         }
764     }
765 
766     /* Verify host controller errors didn't occur */
767     if (object->stat == SD_STATUS_SUCCESS) {
768         /* Wait for the full data transfer to complete */
769         MAP_SDHostIntEnable(hwAttrs->baseAddr, SDHOST_INT_TC);
770 
771         SemaphoreP_pend(object->cmdSem, SemaphoreP_WAIT_FOREVER);
772 
773         MAP_SDHostIntDisable(hwAttrs->baseAddr, SDHOST_INT_TC);
774     }
775 
776     /* Verify host controller errors didn't occur */
777     if (object->stat == SD_STATUS_SUCCESS) {
778         /* Wait for command transfer stop acknowledgment */
779         result = send_cmd(handle, CMD_STOP_TRANS, NULLARG);
780 
781         if (result ==  SD_STATUS_SUCCESS) {
782             MAP_SDHostIntEnable(hwAttrs->baseAddr, SDHOST_INT_TC);
783 
784             SemaphoreP_pend(object->cmdSem, SemaphoreP_WAIT_FOREVER);
785 
786             MAP_SDHostIntDisable(hwAttrs->baseAddr, SDHOST_INT_TC);
787         }
788     }
789 
790     if (object->stat != SD_STATUS_SUCCESS) {
791         result = SD_STATUS_ERROR;
792     }
793 
794     Power_releaseConstraint(PowerCC32XX_DISALLOW_LPDS);
795     DebugP_log1("SDHost:(%p) SDHostCC32XX_write released write power"
796         " constraint", hwAttrs->baseAddr);
797 
798     return (result);
799 }
800 
801 /*
802  *  ======== configDMAChannel ========
803  *  Configures either the primary or alternate DMA control structures in
804  *  ping-pong mode.
805  *  channelSel is the PRI or ALT channel select flag
806  */
configDMAChannel(SD_Handle handle,uint_fast32_t channelSel,uint_fast32_t operation)807 static inline void configDMAChannel(SD_Handle handle, uint_fast32_t channelSel,
808     uint_fast32_t operation)
809 {
810     unsigned long                 channelControlOptions;
811     SDHostCC32XX_Object          *object = handle->object;
812     SDHostCC32XX_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
813 
814     if (operation == UDMAWRITE) {
815         channelControlOptions = UDMA_SIZE_32 | UDMA_SRC_INC_32 |
816             UDMA_DST_INC_NONE | UDMA_ARB_512;
817 
818         /* Primary control structure set-up */
819         MAP_uDMAChannelControlSet(hwAttrs->txChIdx |
820             channelSel, channelControlOptions);
821 
822         /* Transfer size is the sector size in words */
823         MAP_uDMAChannelTransferSet(hwAttrs->txChIdx | channelSel,
824             UDMA_MODE_PINGPONG, (void *)object->buffer,
825             (void *)(hwAttrs->baseAddr + MMCHS_O_DATA), SECTORSIZE / 4);
826     }
827     else {
828         channelControlOptions = UDMA_SIZE_32 | UDMA_SRC_INC_NONE |
829                 UDMA_DST_INC_32 | UDMA_ARB_512;
830 
831         /* Primary control structure set-up */
832         MAP_uDMAChannelControlSet(hwAttrs->rxChIdx |
833             channelSel, channelControlOptions);
834 
835         /* Transfer size is the sector size in words */
836         MAP_uDMAChannelTransferSet(hwAttrs->rxChIdx | channelSel,
837             UDMA_MODE_PINGPONG, (void *)(hwAttrs->baseAddr + MMCHS_O_DATA),
838             (void *)object->buffer, SECTORSIZE / 4);
839     }
840 }
841 
842 /*
843  *  ======== deSelectCard ========
844  *  Function to de-select a card on the drive specified by the handle.
845  */
deSelectCard(SD_Handle handle)846 static int_fast32_t deSelectCard(SD_Handle handle)
847 {
848     int_fast32_t result;
849 
850     /* De-select the card */
851     result = send_cmd(handle, CMD_DESELECT_CARD, NULLARG);
852 
853     return (result);
854 }
855 
856 /*
857  *  ======== getPowerMgrId ========
858  */
getPowerMgrId(uint_fast32_t baseAddr)859 static uint_fast32_t getPowerMgrId(uint_fast32_t baseAddr)
860 {
861     if (baseAddr == SDHOST_BASE) {
862         return (PowerCC32XX_PERIPH_SDHOST);
863     }
864     else {
865         return ((uint_fast32_t)-1);
866     }
867 }
868 
869 /*
870  *  ======== hwiIntFxn ========
871  *  ISR to service pending SD or DMA commands.
872  */
hwiIntFxn(uintptr_t handle)873 static void hwiIntFxn(uintptr_t handle)
874 {
875     uint_fast32_t                 ret;
876     SDHostCC32XX_Object          *object = ((SD_Handle)handle)->object;
877     SDHostCC32XX_HWAttrsV1 const *hwAttrs = ((SD_Handle)handle)->hwAttrs;
878 
879     /* Get interrupt and clear all interrupt flags */
880     ret = MAP_SDHostIntStatus(hwAttrs->baseAddr);
881     MAP_SDHostIntClear(hwAttrs->baseAddr, ret);
882 
883     /* Error or unsupported interrupt occurred */
884     if (ret & SDHOST_INT_ERRI) {
885         object->stat = SD_STATUS_ERROR;
886         SemaphoreP_post(object->cmdSem);
887         return;
888     }
889 
890     /* Command complete flag */
891     if (ret & SDHOST_INT_CC) {
892         if (object->stat != SD_STATUS_ERROR) {
893             object->stat = SD_STATUS_SUCCESS;
894         }
895         SemaphoreP_post(object->cmdSem);
896     }
897 
898     /*
899      * DMA read and write interrupt flags. This interrupt is
900      * generated when a DMA channel finishes a transfer AND when
901      * the SD peripheral empties it's TX or RX buffer. Both events
902      * use the DMA WRITE or DMA READ interrupt flags respectively.
903      */
904     if (ret & (SDHOST_INT_DMARD | SDHOST_INT_DMAWR)) {
905         uint_fast32_t priChannelMode;
906         uint_fast32_t altChannelMode;
907         uint32_t channel = hwAttrs->txChIdx;
908         uint32_t operation = UDMAWRITE;
909 
910         if (ret & SDHOST_INT_DMARD) {
911             channel = hwAttrs->rxChIdx;
912             operation = UDMAREAD;
913         }
914 
915         priChannelMode = MAP_uDMAChannelModeGet(channel | UDMA_PRI_SELECT);
916         altChannelMode = MAP_uDMAChannelModeGet(channel | UDMA_ALT_SELECT);
917 
918         /*
919          * Differentiate between the SD peripheral emptying a buffer
920          * and a DMA channel completing a transfer. If neither DMA
921          * channel is stopped, then we wait for the next interrupt.
922          */
923         if (priChannelMode == UDMA_MODE_STOP ||
924             altChannelMode == UDMA_MODE_STOP) {
925 
926             object->ping = !object->ping;
927             if (object->sectorCount != 0) {
928                 object->sectorCount--;
929             }
930 
931             /*
932              * Check DMA transfers are complete,
933              * otherwise wait for the next interrupt
934              */
935             if (priChannelMode == UDMA_MODE_STOP &&
936                 altChannelMode == UDMA_MODE_STOP &&
937                 object->sectorCount != 0) {
938 
939                 /* Determine if multiple DMA transfers completed */
940                 if (object->ping) {
941                     object->sectorCount--;
942                     object->ping = false;
943                 }
944 
945                 /*
946                  * If sectorCount is 0, then we do not need to configure
947                  * any more DMA transfers.
948                  */
949                 if(object->sectorCount != 0) {
950                     /* Configure the primary DMA channel */
951                     object->buffer = object->buffer + (SECTORSIZE / 4);
952                     configDMAChannel((SD_Handle) handle, UDMA_PRI_SELECT, operation);
953 
954                     /* If more than 1 sector is left, configure pong */
955                     if (object->sectorCount > 1) {
956                         /* Configure the alternate DMA channel */
957                         object->buffer = object->buffer + (SECTORSIZE / 4);
958                         configDMAChannel((SD_Handle) handle, UDMA_ALT_SELECT, operation);
959                     }
960                 }
961             }
962 
963             /* If the DMA has transfered all sectors to the SD peripheral */
964             if (object->sectorCount == 0 && object->dmaPosted == false &&
965                 priChannelMode == UDMA_MODE_STOP &&
966                 altChannelMode == UDMA_MODE_STOP) {
967 
968                 if (object->stat != SD_STATUS_ERROR) {
969                     object->stat = SD_STATUS_SUCCESS;
970                 }
971 
972                 /* Reset to primary channel and disable all DMA interrupts */
973                 MAP_uDMAChannelAttributeDisable(channel, UDMA_ATTR_ALTSELECT);
974                 MAP_SDHostIntDisable(hwAttrs->baseAddr, SDHOST_INT_DMAWR | SDHOST_INT_DMARD);
975                 MAP_SDHostIntClear(hwAttrs->baseAddr, SDHOST_INT_DMAWR | SDHOST_INT_DMARD);
976                 object->dmaPosted = true;
977                 SemaphoreP_post(object->cmdSem);
978             }
979         }
980     }
981 
982     /* Transfer complete flag */
983     if (ret & SDHOST_INT_TC) {
984         if (object->stat != SD_STATUS_ERROR) {
985             object->stat = SD_STATUS_SUCCESS;
986         }
987         SemaphoreP_post(object->cmdSem);
988     }
989 
990     /* Data buffer read ready flag */
991     if (ret & SDHOST_INT_BRR) {
992         if (object->stat != SD_STATUS_ERROR) {
993             object->stat = SD_STATUS_SUCCESS;
994         }
995         SemaphoreP_post(object->cmdSem);
996     }
997 
998     /* Data buffer write ready flag */
999     if (ret & SDHOST_INT_BWR) {
1000         if (object->stat != SD_STATUS_ERROR) {
1001             object->stat = SD_STATUS_SUCCESS;
1002         }
1003         SemaphoreP_post(object->cmdSem);
1004     }
1005 }
1006 
1007 /*
1008  *  ======== initHw ========
1009  */
initHw(SD_Handle handle)1010 static void initHw(SD_Handle handle)
1011 {
1012     SDHostCC32XX_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
1013     uint32_t pin;
1014     uint32_t mode;
1015 
1016     /* Configure for SDHost Data */
1017     pin = PinConfigPin(hwAttrs->dataPin);
1018     mode = PinConfigPinMode(hwAttrs->dataPin);
1019     MAP_PinTypeSDHost(pin, mode);
1020     MAP_PinConfigSet(pin, PIN_STRENGTH_4MA, PIN_TYPE_STD_PU);
1021 
1022     /* Configure for SDHost Command */
1023     pin = PinConfigPin(hwAttrs->cmdPin);
1024     mode = PinConfigPinMode(hwAttrs->cmdPin);
1025     MAP_PinTypeSDHost(pin, mode);
1026     MAP_PinConfigSet(pin, PIN_STRENGTH_4MA, PIN_TYPE_STD_PU);
1027 
1028     /* Configure for SDHost clock output */
1029     pin = PinConfigPin(hwAttrs->clkPin);
1030     mode = PinConfigPinMode(hwAttrs->clkPin);
1031     MAP_PinTypeSDHost(pin, mode);
1032     MAP_PinDirModeSet(pin, PIN_DIR_MODE_OUT);
1033 
1034     MAP_PRCMPeripheralReset(PRCM_SDHOST);
1035     MAP_SDHostInit(hwAttrs->baseAddr);
1036 
1037     MAP_SDHostIntDisable(hwAttrs->baseAddr, SDHOST_INT_CC | SDHOST_INT_TC |
1038         SDHOST_INT_DMAWR | SDHOST_INT_DMARD | SDHOST_INT_BRR | SDHOST_INT_BWR);
1039 
1040     /* Configure card clock */
1041     MAP_SDHostSetExpClk(hwAttrs->baseAddr,
1042         MAP_PRCMPeripheralClockGet(PRCM_SDHOST), hwAttrs->clkRate);
1043 
1044     MAP_SDHostIntClear(hwAttrs->baseAddr, SDHOST_INT_CC | SDHOST_INT_TC |
1045         DATAERROR | CMDERROR | SDHOST_INT_DMAWR | SDHOST_INT_DMARD |
1046         SDHOST_INT_BRR | SDHOST_INT_BWR);
1047 
1048     /*
1049      * DMA channels 23 and 24 are connected to the SD peripheral by default.
1050      * If someone hasn't remapped them to something else already, we remap
1051      * them to SW.
1052      */
1053     if (!(HWREG(UDMA_BASE + UDMA_O_CHMAP2) & UDMA_CHMAP2_CH23SEL_M)) {
1054         MAP_uDMAChannelAssign(UDMA_CH23_SW);
1055     }
1056     if (!(HWREG(UDMA_BASE + UDMA_O_CHMAP3) & UDMA_CHMAP3_CH24SEL_M)) {
1057         MAP_uDMAChannelAssign(UDMA_CH24_SW);
1058     }
1059 
1060     /* Configure DMA for TX and RX */
1061     MAP_uDMAChannelAssign(hwAttrs->txChIdx);
1062     MAP_uDMAChannelAssign(hwAttrs->rxChIdx);
1063 
1064     MAP_uDMAChannelEnable(hwAttrs->txChIdx);
1065     MAP_uDMAChannelEnable(hwAttrs->rxChIdx);
1066 
1067     /* Enable SDHost Error Interrupts */
1068     MAP_SDHostIntEnable(hwAttrs->baseAddr, DATAERROR | CMDERROR);
1069 }
1070 
1071 
1072 /*
1073  *  ======== postNotifyFxn ========
1074  *  Called by Power module when waking up from LPDS.
1075  */
postNotifyFxn(unsigned int eventType,uintptr_t eventArg,uintptr_t clientArg)1076 static int postNotifyFxn(unsigned int eventType, uintptr_t eventArg,
1077         uintptr_t clientArg)
1078 {
1079     initHw((SD_Handle)clientArg);
1080 
1081     return (Power_NOTIFYDONE);
1082 }
1083 
1084 /*
1085  *  ======== send_cmd ========
1086  *  Function to send a command to the SD Card
1087  */
send_cmd(SD_Handle handle,uint_fast32_t cmd,uint_fast32_t arg)1088 static int_fast32_t send_cmd(SD_Handle handle, uint_fast32_t cmd,
1089     uint_fast32_t arg)
1090 {
1091     int_fast32_t                  result  = SD_STATUS_SUCCESS;
1092     SDHostCC32XX_Object          *object  = handle->object;
1093     SDHostCC32XX_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
1094 
1095     /* Enable command complete interrupts */
1096     MAP_SDHostIntEnable(hwAttrs->baseAddr, SDHOST_INT_CC);
1097 
1098     /* Send the command */
1099     MAP_SDHostCmdSend(hwAttrs->baseAddr, cmd, arg);
1100 
1101     SemaphoreP_pend(object->cmdSem, SemaphoreP_WAIT_FOREVER);
1102 
1103     MAP_SDHostIntDisable(hwAttrs->baseAddr, SDHOST_INT_CC);
1104 
1105     /* SD Card Error, reset the command line */
1106     if (object->stat == SD_STATUS_ERROR) {
1107         MAP_SDHostCmdReset(hwAttrs->baseAddr);
1108         result = SD_STATUS_ERROR;
1109     }
1110 
1111     return (result);
1112 }
1113 
1114 /*
1115  *  ======== selectCard ========
1116  *  Function to select a card on the specified drive.
1117  */
selectCard(SD_Handle handle)1118 static int_fast32_t selectCard(SD_Handle handle)
1119 {
1120     int_fast32_t                  result;
1121     SDHostCC32XX_Object          *object  = handle->object;
1122     SDHostCC32XX_HWAttrsV1 const *hwAttrs = handle->hwAttrs;
1123 
1124     /* Select the card */
1125     result = send_cmd(handle, CMD_SELECT_CARD, object->rca << 16);
1126 
1127     if (result == SD_STATUS_SUCCESS) {
1128         /* Wait for transfer compelte interrupt */
1129         MAP_SDHostIntEnable(hwAttrs->baseAddr, SDHOST_INT_TC);
1130 
1131         SemaphoreP_pend(object->cmdSem, SemaphoreP_WAIT_FOREVER);
1132 
1133         MAP_SDHostIntDisable(hwAttrs->baseAddr, SDHOST_INT_TC);
1134 
1135         /* Host controller error occurred */
1136         if (object->stat != SD_STATUS_SUCCESS) {
1137             result = SD_STATUS_ERROR;
1138         }
1139     }
1140     return (result);
1141 }
1142