~aleteoryx/muditaos

ref: d02a8e446ec5a7c3b21e8eb8f312853fa0b8f6b1 muditaos/module-vfs/board/rt1051/purefs/src/blkdev/disk_emmc.cpp -rw-r--r-- 3.7 KiB
d02a8e44 — Hubert Chrzaniuk [EGD-5014] Change MMC erase logic 5 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <purefs/blkdev/disk_emmc.hpp>
#include <unistd.h>
#include <cstring>
#include <task.h>

namespace purefs::blkdev
{
    disk_emmc::disk_emmc()
    {
        mmcCard.busWidth                   = kMMC_DataBusWidth8bit;
        mmcCard.busTiming                  = kMMC_HighSpeedTiming;
        mmcCard.enablePreDefinedBlockCount = true;
        mmcCard.host.base                  = USDHC2;
        mmcCard.host.sourceClock_Hz        = GetPerphSourceClock(PerphClock_USDHC2);
    }

    auto disk_emmc::probe(unsigned int flags) -> int
    {
        cpp_freertos::LockGuard lock(mutex);
        auto err = MMC_Init(&mmcCard);
        if (err != kStatus_Success) {
            initStatus = err;
            return initStatus;
        }
        return statusBlkDevSuccess;
    }

    auto disk_emmc::cleanup() -> int
    {
        cpp_freertos::LockGuard lock(mutex);
        if (!mmcCard.isHostReady) {
            return statusBlkDevFail;
        }
        MMC_Deinit(&mmcCard);
        return statusBlkDevSuccess;
    }

    auto disk_emmc::write(const void *buf, sector_t lba, std::size_t count) -> int
    {
        cpp_freertos::LockGuard lock(mutex);
        if (!mmcCard.isHostReady || buf == nullptr) {
            return statusBlkDevFail;
        }
        auto err = MMC_WriteBlocks(&mmcCard, static_cast<const uint8_t *>(buf), lba, count);
        if (err != kStatus_Success) {
            return err;
        }
        return statusBlkDevSuccess;
    }

    auto disk_emmc::erase(sector_t lba, std::size_t count) -> int
    {
        // erase group size is 512kB so it has been deliberately disallowed
        // group of this size would make the solution inefficient in this case
        return statusBlkDevSuccess;
    }
    auto disk_emmc::read(void *buf, sector_t lba, std::size_t count) -> int
    {
        cpp_freertos::LockGuard lock(mutex);
        if (!mmcCard.isHostReady || buf == nullptr) {
            return statusBlkDevFail;
        }
        auto err = MMC_ReadBlocks(&mmcCard, static_cast<uint8_t *>(buf), lba, count);
        if (err != kStatus_Success) {
            return err;
        }
        return statusBlkDevSuccess;
    }
    auto disk_emmc::sync() -> int
    {
        cpp_freertos::LockGuard lock(mutex);
        if (!mmcCard.isHostReady) {
            return statusBlkDevFail;
        }
        // Wait for the card's buffer to become empty
        while ((GET_SDMMCHOST_STATUS(mmcCard.host.base) & CARD_DATA0_STATUS_MASK) != CARD_DATA0_NOT_BUSY) {
            taskYIELD();
        }

        if (kStatus_Success != MMC_WaitWriteComplete(&mmcCard)) {
            return kStatus_SDMMC_WaitWriteCompleteFailed;
        }
        return statusBlkDevSuccess;
    }
    auto disk_emmc::status() const -> media_status
    {
        cpp_freertos::LockGuard lock(mutex);
        if (initStatus != kStatus_Success) {
            return media_status::error;
        }
        if (!mmcCard.isHostReady) {
            return media_status::uninit;
        }
        if ((mmcCard.csd.flags & kMMC_CsdPermanentWriteProtectFlag) ||
            (mmcCard.csd.flags & kMMC_CsdTemporaryWriteProtectFlag)) {
            return media_status::wprotect;
        }
        return media_status::healthly;
    }

    auto disk_emmc::get_info(info_type what) const -> scount_t
    {
        cpp_freertos::LockGuard lock(mutex);
        switch (what) {
        case info_type::sector_size:
            return mmcCard.blockSize;
        case info_type::sector_count:
            return mmcCard.userPartitionBlocks;
        case info_type::erase_block:
            // not supported
            return 0;
        }
        return -1;
    }
} // namespace purefs::blkdev