blob: 5e7968619a83b617ef5f558de4b88a6d0efde9cb [file]
// Copyright 2023 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.
#ifndef SRC_DEVICES_BLOCK_DRIVERS_UFS_TRANSFER_COMMAND_DESCRIPTOR_H_
#define SRC_DEVICES_BLOCK_DRIVERS_UFS_TRANSFER_COMMAND_DESCRIPTOR_H_
#include <zircon/syscalls.h>
#include <hwreg/bitfields.h>
namespace ufs {
// According to the UFSHCI specification, the size of the UTP command descriptor is as follows. The
// size of the transfer request is not limited, a transfer response can be as long as 65535 *
// dwords, and a PRDT can be as long as 65565 * PRDT entry size(16 bytes).
// However, for ease of use, this UFS Driver imposes the following limits. The size of the transfer
// request and the transfer response is 1024 bytes or less. The PRDT region limits the number of
// scatter gathers to 256, using a total of 4096 bytes. Therefore, only 8KB size is allocated for
// the UTP command descriptor.
constexpr size_t kUtpCommandDescriptorSize = 8192;
constexpr size_t kMaxUtpTransferRequestSize = 512;
constexpr size_t kMaxUtpTransferResponseSize = 512;
// To reduce the size of the UTP Command Descriptor(8KB), we must use only 256 PRDT entries.
constexpr uint32_t kMaxPrdtEntryCount = 256;
// Set the PRDT data length to 4KB in order to scatter gather per page.
const uint32_t kPrdtEntryDataLength = zx_system_get_page_size();
// The UFS specification allows for up to 16GB, but we limits the number of PRDT entries to 256, so
// we can use up to 1MiB.
const uint32_t kMaxPrdtDataLength = kMaxPrdtEntryCount * kPrdtEntryDataLength; // 1MiB
// UFSHCI Specification Version 3.0, section 6.1.2 "UTP Command Descriptor".
struct PhysicalRegionDescriptionTableEntry {
uint32_t dwords[4];
// dword 0
DEF_SUBFIELD(dwords[0], 31, 0, data_base_address);
// dword 1
DEF_SUBFIELD(dwords[1], 31, 0, data_base_address_upper);
// dword 3
DEF_SUBFIELD(dwords[3], 17, 0, data_byte_count); // Maximum byte count is 256KB
} __PACKED;
static_assert(sizeof(PhysicalRegionDescriptionTableEntry) == 16,
"PhysicalRegionDescriptionTableEntry struct must be 16 bytes");
static_assert(
(kMaxUtpTransferRequestSize + kMaxUtpTransferResponseSize +
sizeof(PhysicalRegionDescriptionTableEntry) * kMaxPrdtEntryCount) <= kUtpCommandDescriptorSize,
"The sum of the sizes of the Request, Response, and PRDT must be kUtpCommandDescriptorSize or "
"less");
} // namespace ufs
#endif // SRC_DEVICES_BLOCK_DRIVERS_UFS_TRANSFER_COMMAND_DESCRIPTOR_H_