Commit 17fb10a8 authored by Ben Avison's avatar Ben Avison Committed by ROOL
Browse files

Support controllers with lower block size limits

Some controllers (such as the eMMC controller in the Pinebook) require
transfers to be limited to a smaller number of blocks per operation than is
permitted by a generic SDHCI controller.
parent a5d87d20
......@@ -546,7 +546,7 @@ low_level_error_t discop(uint32_t reason,
* separate code path for older cards that won't be tested properly, we assume
* the worst case. Constraints are:
* - must start and end on read/write block boundaries (may require read-modify-write)
* - must not exceed 65535*512-byte blocks (SDHCI limitation)
* - must not exceed 65535*512-byte blocks (SDHCI limitation - or less for some controllers)
* - must not exceed 4MB (for some controllers when operating in UHS mode)
* - some MMC cards have 4K sectors, and all operations must be done in multiples
* of 8*512-byte blocks (we can make this fall out of the block boundary restriction)
......@@ -557,7 +557,7 @@ low_level_error_t discop(uint32_t reason,
uint64_t start_down = ROUND_DOWN_64(*disc_address, align_size);
uint64_t end_down = ROUND_DOWN_64(*disc_address + *fg_length, align_size);
uint64_t end_up = ROUND_UP_64(*disc_address + *fg_length, align_size);
uint32_t chunk_size = ROUND_DOWN_32(0xFFFF << LOG2_SECTOR_SIZE, align_size);
uint32_t chunk_size = ROUND_DOWN_32(dr->maxblkcount << LOG2_SECTOR_SIZE, align_size);
if (dr->single_blocks)
chunk_size = 1 << LOG2_SECTOR_SIZE;
dprintf("align=%u, %016"PRIX64"/%016"PRIX64"/%016"PRIX64", chunk=%08X\n", align_size, start_down, end_down, end_up, chunk_size);
......
......@@ -70,6 +70,11 @@ void service_SDIOSlotAttached(uint32_t bus, uint32_t slot, bool integrated, bool
g_drive[i].card_inserted = false;
g_drive[i].bus = bus;
g_drive[i].slot = slot;
if (_swix(SDIO_ControllerFeatures, _INR(0,1)|_OUT(2),
SDIOController_MaxBlockCount,
(bus << SDIOController_BusShift) | (slot << SDIOController_SlotShift),
&g_drive[i].maxblkcount))
g_drive[i].maxblkcount = 0xFFFF;
barrier(); /* because we may read these from the background */
g_drive[i].slot_attached = true;
upcall(UpCall_DriveAdded, i);
......@@ -205,6 +210,11 @@ void service_SDIOUnitAttached(uint32_t bus, uint32_t slot, uint32_t rca, uint32_
g_drive[i].card_inserted = false;
g_drive[i].bus = bus;
g_drive[i].slot = slot;
if (_swix(SDIO_ControllerFeatures, _INR(0,1)|_OUT(2),
SDIOController_MaxBlockCount,
(bus << SDIOController_BusShift) | (slot << SDIOController_SlotShift),
&g_drive[i].maxblkcount))
g_drive[i].maxblkcount = 0xFFFF;
barrier(); /* because we may read these from the background */
g_drive[i].slot_attached = true;
dprintf("Allocate additional drive %u for bus %u / slot %u\n", i, bus, slot);
......
......@@ -246,6 +246,7 @@ typedef struct
bool slot_claimed; /**< Part of the mechanism for detecting other users of this drive's slot */
bool needs_reselect; /**< Card state is unknown, needs to be set up (again) */
bool needs_wait; /**< Card's last operation was or might be a write operation, so wait for it to return to tran state */
uint32_t maxblkcount; /**< maximum number of blocks per operation */
uint8_t bus; /**< SDIODriver bus number */
uint8_t slot; /**< SDIODriver slot number */
uint16_t rca; /**< Card RCA */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment