1 /*
2  * The Clear BSD License
3  * Copyright (c) 2015, Freescale Semiconductor, Inc.
4  * Copyright 2016 NXP
5  * All rights reserved.
6  *
7  *
8  * Redistribution and use in source and binary forms, with or without modification,
9  * are permitted (subject to the limitations in the disclaimer below) provided
10  *  that the following conditions are met:
11  *
12  * o Redistributions of source code must retain the above copyright notice, this list
13  *   of conditions and the following disclaimer.
14  *
15  * o Redistributions in binary form must reproduce the above copyright notice, this
16  *   list of conditions and the following disclaimer in the documentation and/or
17  *   other materials provided with the distribution.
18  *
19  * o Neither the name of the copyright holder nor the names of its
20  *   contributors may be used to endorse or promote products derived from this
21  *   software without specific prior written permission.
22  *
23  * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  * DISCLAIMED. IN NO EVENT SL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 #include <assert.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include "fsl_mmc.h"
40 #include "fsl_mmc_disk.h"
41 #include "diskio.h"
42 
43 /* New project wizard guide note. */
44 #ifndef BOARD_MMC_VCC_SUPPLY
45 #error Undefined macro. Define BOARD_MMC_VCC_SUPPLY in board.h
46 #endif
47 
48 /*******************************************************************************
49  * Definitons
50  ******************************************************************************/
51 
52 /*******************************************************************************
53  * Prototypes
54  ******************************************************************************/
55 
56 /*******************************************************************************
57  * Variables
58  ******************************************************************************/
59 
60 /*! @brief Card descriptor */
61 static mmc_card_t g_mmc;
62 
63 /*******************************************************************************
64  * Code
65  ******************************************************************************/
66 
mmc_disk_write(uint8_t physicalDrive,const uint8_t * buffer,uint32_t sector,uint8_t count)67 DRESULT mmc_disk_write(uint8_t physicalDrive, const uint8_t *buffer, uint32_t sector, uint8_t count)
68 {
69     if (physicalDrive != MMCDISK) {
70         return RES_PARERR;
71     }
72 
73     if (kStatus_Success != MMC_WriteBlocks(&g_mmc, buffer, sector, count)) {
74         return RES_ERROR;
75     }
76 
77     return RES_OK;
78 }
79 
mmc_disk_read(uint8_t physicalDrive,uint8_t * buffer,uint32_t sector,uint8_t count)80 DRESULT mmc_disk_read(uint8_t physicalDrive, uint8_t *buffer, uint32_t sector, uint8_t count)
81 {
82     if (physicalDrive != MMCDISK) {
83         return RES_PARERR;
84     }
85 
86     if (kStatus_Success != MMC_ReadBlocks(&g_mmc, buffer, sector, count)) {
87         return RES_ERROR;
88     }
89 
90     return RES_OK;
91 }
92 
mmc_disk_ioctl(uint8_t physicalDrive,uint8_t command,void * buffer)93 DRESULT mmc_disk_ioctl(uint8_t physicalDrive, uint8_t command, void *buffer)
94 {
95     DRESULT res = RES_OK;
96 
97     if (physicalDrive != MMCDISK) {
98         return RES_PARERR;
99     }
100 
101     switch (command) {
102         case GET_SECTOR_COUNT:
103             if (buffer) {
104                 *(uint32_t *)buffer = g_mmc.userPartitionBlocks;
105             } else {
106                 res = RES_PARERR;
107             }
108 
109             break;
110 
111         case GET_SECTOR_SIZE:
112             if (buffer) {
113                 *(uint32_t *)buffer = g_mmc.block_size;
114             } else {
115                 res = RES_PARERR;
116             }
117 
118             break;
119 
120         case GET_BLOCK_SIZE:
121             if (buffer) {
122                 *(uint32_t *)buffer = g_mmc.eraseGroupBlocks;
123             } else {
124                 res = RES_PARERR;
125             }
126 
127             break;
128 
129         case CTRL_SYNC:
130             res = RES_OK;
131             break;
132 
133         default:
134             res = RES_PARERR;
135             break;
136     }
137 
138     return res;
139 }
140 
mmc_disk_status(uint8_t physicalDrive)141 DSTATUS mmc_disk_status(uint8_t physicalDrive)
142 {
143     if (physicalDrive != MMCDISK) {
144         return STA_NOINIT;
145     }
146 
147     return RES_OK;
148 }
149 
mmc_disk_initialize(uint8_t physicalDrive)150 DSTATUS mmc_disk_initialize(uint8_t physicalDrive)
151 {
152     if (physicalDrive != MMCDISK) {
153         return STA_NOINIT;
154     }
155 
156     /* Save host information. */
157     g_mmc.host.base = MMC_HOST_BASEADDR;
158     g_mmc.host.source_clock_hz = MMC_HOST_CLK_FREQ;
159 
160     /* MMC card VCC supply, only allow 3.3 or 1.8v, depend on your board config.
161     * If a power reset circuit is avaliable on you board for mmc, and 1.8v is supported,
162     * #define BOARD_USDHC_MMCCARD_POWER_CONTROL_INIT()
163     * #define BOARD_USDHC_MMCCARD_POWER_CONTROL(state)
164     * in board.h must be implemented.
165     * User can remove preset the voltage window and sdmmc will switch VCC automatically. */
166     g_mmc.hostVoltageWindowVCC = BOARD_MMC_VCC_SUPPLY;
167 
168     if (kStatus_Success != MMC_Init(&g_mmc)) {
169         MMC_Deinit(&g_mmc);
170         memset(&g_mmc, 0U, sizeof(g_mmc));
171         return STA_NOINIT;
172     }
173 
174     return RES_OK;
175 }
176