blob: cc635abc7ec10cd4029afd4fde45899d710a4cd2 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include "mtk-sdmmc.h"
namespace {
static constexpr size_t kDescriptorChecksumSize = 16;
static constexpr uint64_t kAddressMask = 0xffffffff;
uint32_t CalculateChecksum(const void* buf) {
const uint8_t* buf_u8 = reinterpret_cast<const uint8_t*>(buf);
uint32_t sum = 0;
for (size_t i = 0; i < kDescriptorChecksumSize; i++) {
sum += buf_u8[i];
}
return (0xff - (sum & 0xff)) & 0xff;
}
} // namespace
namespace sdmmc {
struct GpDmaDescriptor {
void SetNext(uint64_t addr) {
info = GpDmaDescriptorInfo().set_reg_value(info).set_next_addr(addr).reg_value();
next = addr & kAddressMask;
}
void SetBDmaDesc(uint64_t addr) {
info = GpDmaDescriptorInfo().set_reg_value(info).set_bdma_desc_addr(addr).reg_value();
bdma_desc = addr & kAddressMask;
}
void SetChecksum() {
auto info_reg = GpDmaDescriptorInfo().set_reg_value(info).set_checksum(0);
info = info_reg.reg_value();
info = info_reg.set_checksum(CalculateChecksum(this)).reg_value();
}
uint32_t info = 0; // See GpDmaDescriptorInfo in mtk-sdmmc-reg.h.
uint32_t next = 0; // Physical address of the next GpDmaDesecriptor.
uint32_t bdma_desc = 0; // Physical address of the BDmaDescriptor.
uint32_t size = 0; // Values here and below are ignored when using one GPDMA descriptor at
uint32_t arg = 0; // a time.
uint32_t blknum = 0;
uint32_t cmd = 0;
};
struct BDmaDescriptor {
static constexpr size_t kMaxBufferSize = 0xffff & ~kPageMask;
static_assert(kMaxBufferSize > 0);
static_assert(kMaxBufferSize % PAGE_SIZE == 0);
void SetNext(uint64_t addr) {
info = BDmaDescriptorInfo().set_reg_value(info).set_next_addr(addr).reg_value();
next = addr & kAddressMask;
}
void SetBuffer(uint64_t addr) {
info = BDmaDescriptorInfo().set_reg_value(info).set_buffer_addr(addr).reg_value();
buffer = addr & kAddressMask;
}
void SetChecksum() {
auto info_reg = BDmaDescriptorInfo().set_reg_value(info).set_checksum(0);
info = info_reg.reg_value();
info = info_reg.set_checksum(CalculateChecksum(this)).reg_value();
}
uint32_t info = 0; // See BDmaDescriptorInfo in mtk-sdmmc-reg.h.
uint32_t next = 0; // Physical address of the next BDmaDescriptor.
uint32_t buffer = 0; // Physical address of the data buffer.
uint32_t size = 0; // Size of the data buffer.
};
} // namespace sdmmc