Commit 0bde08c0 authored by Ben Avison's avatar Ben Avison
Browse files

Add SDIO_Status call to query max block size from SDIO CIS data

This saves client programs the trouble of implementing a CIS parser to
extract this information.
parent 507e7f85
Pipeline #6395 passed with stages
in 48 seconds
......@@ -364,6 +364,12 @@ _kernel_oserror *module_swi(int swi_offset, _kernel_swi_regs *r, void *pw)
(r->r[1] & SDIOStatus_SlotMask) >> SDIOStatus_SlotShift,
(uint32_t *) &r->r[0]);
case SDIOStatus_FunctionMaxBlockLen:
return swi_Status_function_max_block_length((r->r[1] & SDIOStatus_BusMask) >> SDIOStatus_BusShift,
(r->r[1] & SDIOStatus_SlotMask) >> SDIOStatus_SlotShift,
(r->r[1] & SDIOStatus_UnitMask) >> SDIOStatus_UnitShift,
(uint32_t *) &r->r[0]);
default:
return MESSAGE_ERRORLOOKUP(true, SDIO_BadReason, "SDIO_Status");
}
......
......@@ -1319,6 +1319,8 @@ static bool resolve_bus_speed(ctrlnode_t *ctrl, uint32_t sloti)
return false;
dprintf("IO TRAN_SPEED = %u kbps\n", cid_bitrate);
slot->freq = MIN(slot->freq, slot->ddr ? cid_bitrate / 2 : cid_bitrate);
/* While we're here, extract the maximum block size for function 0 */
slot->function_maxblklen[0] = buffer[1] | (buffer[2] << 8);
e = select_deselect_card(ctrl, sloti, 0, NULL);
if (e != NULL)
ABORT_PROBE("SELECT_DESELECT_CARD returned %s\n", e->errmess);
......@@ -1498,6 +1500,11 @@ static bool read_fic(ctrlnode_t *ctrl, uint32_t sloti)
read_cis_tuple(ctrl, sloti, 0, CISTPL_MANFID, buffer, 4);
slot->io_manf[function-1] = *(uint16_t *) buffer;
slot->io_card[function-1] = *(uint16_t *) (buffer+2);
/* Try to find a CISTPL_FUNCE tuple to yield max block size */
memset(buffer, 0, 14); /* ensure 0 if not found */
read_cis_tuple(ctrl, sloti, function, CISTPL_FUNCE, buffer, 14);
slot->function_maxblklen[function/* not -1 */] = buffer[12] | (buffer[13] << 8);
}
e = select_deselect_card(ctrl, sloti, 0, NULL);
if (e != NULL)
......
......@@ -873,7 +873,7 @@ _kernel_oserror *swi_ClaimDeviceVector(uint32_t bus, uint32_t sloti, uint32_t un
_kernel_oserror *e = util_find_bus_and_slot(bus, sloti, &ctrl, &slot);
if (e != NULL)
return e;
if (unit == 0 || unit > MAX_FUNCTIONS)
if (unit == 0 || unit > slot->io_functions)
{
spinrw_read_unlock(&g_ctrl_lock);
return MESSAGE_ERRORLOOKUP(true, SDIO_BadUnit, 0);
......@@ -908,7 +908,7 @@ _kernel_oserror *swi_ReleaseDeviceVector(uint32_t bus, uint32_t sloti, uint32_t
_kernel_oserror *e = util_find_bus_and_slot(bus, sloti, &ctrl, &slot);
if (e != NULL)
return e;
if (unit == 0 || unit > MAX_FUNCTIONS)
if (unit == 0 || unit > slot->io_functions)
{
spinrw_read_unlock(&g_ctrl_lock);
return MESSAGE_ERRORLOOKUP(true, SDIO_BadUnit, 0);
......@@ -965,5 +965,24 @@ _kernel_oserror *swi_Status_current_rca(uint32_t bus, uint32_t sloti, uint32_t *
return e;
*result = slot->selected_rca;
spinrw_read_unlock(&g_ctrl_lock);
return NULL;
}
_kernel_oserror *swi_Status_function_max_block_length(uint32_t bus, uint32_t sloti, uint32_t unit, uint32_t *result)
{
ctrlnode_t *ctrl;
sdmmcslot_t *slot;
_kernel_oserror *e = util_find_bus_and_slot(bus, sloti, &ctrl, &slot);
if (e != NULL)
return e;
if (slot->io_functions == 0 || unit > slot->io_functions)
{
spinrw_read_unlock(&g_ctrl_lock);
return MESSAGE_ERRORLOOKUP(true, SDIO_BadUnit, 0);
}
*result = slot->function_maxblklen[unit];
spinrw_read_unlock(&g_ctrl_lock);
return NULL;
}
......@@ -1053,8 +1053,9 @@ SWI SDIO_Status 0 (SWI &59008)
On entry
R0 = 0 (reason code: read currently-selected RCA)
R1 bits 0-7 = slot number
bits 8-15 = bus number
R1 bits 0-7 = unit number (ignored)
bits 8-15 = slot number
bits 16-23 = bus number
On exit
R0 = RCA of selected card, or 0 if none
......@@ -1072,6 +1073,31 @@ it possible to reduce the frequency of issuing of select/deselect CMD7
operations.
SWI SDIO_Status 1 (SWI &59008)
On entry
R0 = 1 (reason code: read maximum block length for IO transfers)
R1 bits 0-7 = unit number, or 0 for CIA
bits 8-15 = slot number
bits 16-23 = bus number
On exit
R0 = maximum block length in bytes, or 0 if information not available
Reentrant
Each SDIO function reports its maximum supported block size in the tuple
CISTPL_FUNCE within its Card Information Structure. SDIODriver caches this
information during bus probe, and makes it available via this SWI.
While SDIODriver usually defines unit 0 to refer to memory operations, in
the case of this SWI, we use 0 to refer to the Common I/O Area (CIA), which is
also known as function 0.
The maximum block length also specifies the limit to the number of bytes that
may be transferred in non-block mode.
*SDIODevices
This command prints out a table of information about the currently known SDIO
......
......@@ -252,6 +252,7 @@ typedef struct
char io_product_info[MAX_FUNCTIONS][32]; /**< product information string from CISTPL_VERS_1, or "SDIO" if none */
uint16_t io_manf[MAX_FUNCTIONS]; /**< SDIO card manufacturer code */
uint16_t io_card[MAX_FUNCTIONS]; /**< SDIO card manufacturer information (typically model/revision info) */
uint16_t function_maxblklen[1+MAX_FUNCTIONS]; /**< maximum block size and byte count that SDIO function can support (note, an entry is present for function 0) */
uint16_t selected_rca; /**< which card is selected (determined by snooping CMD7) */
spinlock_t normal_irqs_lock; /**< lock protecting soft copy of interrupt enables */
uint16_t normal_irqs; /**< soft copy of normal_interrupt_status_enable */
......
......@@ -53,5 +53,6 @@ _kernel_oserror *swi_Op(sdioop_block_t *b);
_kernel_oserror *swi_ClaimDeviceVector(uint32_t bus, uint32_t sloti, uint32_t unit, void *handler, void *pw);
_kernel_oserror *swi_ReleaseDeviceVector(uint32_t bus, uint32_t sloti, uint32_t unit, void *handler, void *pw);
_kernel_oserror *swi_Status_current_rca(uint32_t bus, uint32_t sloti, uint32_t *result);
_kernel_oserror *swi_Status_function_max_block_length(uint32_t bus, uint32_t sloti, uint32_t unit, uint32_t *result);
#endif
......@@ -197,12 +197,15 @@ SDIOCDV_BusMask * &FF :SHL: SDIOCDV_BusShift
; SDIO_Status reason codes
^ 0
SDIOStatus_CurrentRCA # 1
SDIOStatus_FunctionMaxBlockLen # 1
; SDIO_Status flags
SDIOStatus_SlotShift * 0
SDIOStatus_UnitShift * 0
SDIOStatus_UnitMask * &FF :SHL: SDIOStatus_UnitShift
SDIOStatus_SlotShift * 8
SDIOStatus_SlotMask * &FF :SHL: SDIOStatus_SlotShift
SDIOStatus_BusShift * 8
SDIOStatus_BusShift * 16
SDIOStatus_BusMask * &FF :SHL: SDIOStatus_BusShift
; Service calls
......
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