Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@

#define VCTAG_GETCLKSTATE 0x00030001
#define VCTAG_GETCLKRATE 0x00030002
#define VCTAG_GETMAXCLKRATE 0x00030004
#define VCTAG_GETVOLTAGE 0x00030003
#define VCTAG_GETCLKMAX 0x00030004
#define VCTAG_GETVOLTMAX 0x00030005
Expand Down
13 changes: 11 additions & 2 deletions arch/arm-native/soc/broadcom/2708/sdcard/sdcard_bcm2708bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,17 @@ ULONG FNAME_SDCBUS(GetClockDiv)(ULONG speed, struct sdcard_Bus *bus)
{
ULONG __BCMClkDiv;

for (__BCMClkDiv = 0; __BCMClkDiv < V300_MAXCLKDIV; __BCMClkDiv++) {
if ((bus->sdcb_ClockMax / (__BCMClkDiv + 1)) <= speed)
/*
* The value programmed into CLOCK_CONTROL is not a divisor: SDHCI runs
* the card at base/(2*N), and N of zero is the special case that passes
* the base clock straight through. V300_MAXCLKDIV is the largest divisor,
* so the largest N is half of it.
*/
if (speed >= bus->sdcb_ClockMax)
return 0;

for (__BCMClkDiv = 1; __BCMClkDiv < (V300_MAXCLKDIV / 2); __BCMClkDiv++) {
if ((bus->sdcb_ClockMax / (__BCMClkDiv * 2)) <= speed)
break;
}

Expand Down
57 changes: 53 additions & 4 deletions arch/arm-native/soc/broadcom/2708/sdcard/sdcard_bcm2708init.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ static void FNAME_BCMSDC(SDBusInit)(struct sdcard_Bus *bus)
SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT |
SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT |
SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL |
SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE;
SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE |
SDHCI_INT_ADMA_ERROR;

FNAME_SDCBUS(SetClock)(bus->sdcb_ClockMin, bus);
FNAME_SDCBUS(SetPowerLevel)(bus->sdcb_Power, FALSE, bus);
Expand Down Expand Up @@ -204,6 +205,31 @@ static int FNAME_BCMSDC(BCM2708Init)(struct SDCardBase *SDCardBase)
__BCM2708Bus->sdcb_BusIRQ = ctrlIRQ;

__BCM2708Bus->sdcb_ClockMax = AROS_LE2LONG(MBoxMessage[6]);

/*
* GETCLKRATE answers with the rate the clock is running at, and on
* BCM2711 the EMMC2 clock is parked until something asks for it, so
* the answer is zero and the card never gets clocked. Ask what the
* clock can do instead.
*/
if (__BCM2708Bus->sdcb_ClockMax == 0)
{
MBoxMessage[0] = AROS_LONG2LE(8 * 4);
MBoxMessage[1] = AROS_LONG2LE(VCTAG_REQ);
MBoxMessage[2] = AROS_LONG2LE(VCTAG_GETMAXCLKRATE);
MBoxMessage[3] = AROS_LONG2LE(8);
MBoxMessage[4] = AROS_LONG2LE(4);
MBoxMessage[5] = AROS_LONG2LE(ctrlClock);
MBoxMessage[6] = 0;
MBoxMessage[7] = 0;

MBoxWrite((APTR)VCMB_BASE, VCMB_PROPCHAN, MBoxMessage);
if (MBoxRead((APTR)VCMB_BASE, VCMB_PROPCHAN) == MBoxMessage)
__BCM2708Bus->sdcb_ClockMax = AROS_LE2LONG(MBoxMessage[6]);

DINIT(bug("[SDCard--] %s: clock was parked, max rate %d Hz\n",
__PRETTY_FUNCTION__, __BCM2708Bus->sdcb_ClockMax));
}
__BCM2708Bus->sdcb_ClockMin = BCM2708SDCLOCK_MIN;

__BCM2708Bus->sdcb_LEDCtrl = (BYTE (*)(int))FNAME_BCMSDCBUS(BCMLEDCtrl);
Expand Down Expand Up @@ -261,9 +287,6 @@ static int FNAME_BCMSDC(BCM2708Init)(struct SDCardBase *SDCardBase)

FNAME_SDCBUS(SoftReset)(SDHCI_RESET_ALL, __BCM2708Bus);

DINIT(bug("[SDCard--] %s: SDHC Max Clock Rate : %dMHz\n", __PRETTY_FUNCTION__, __BCM2708Bus->sdcb_ClockMax / 1000000));
DINIT(bug("[SDCard--] %s: SDHC Min Clock Rate : %dHz (hardcoded)\n", __PRETTY_FUNCTION__, __BCM2708Bus->sdcb_ClockMin));

__BCM2708Bus->sdcb_Version = FNAME_BCMSDCBUS(BCMMMIOReadWord)(SDHCI_HOST_VERSION, __BCM2708Bus);
__BCM2708Bus->sdcb_Capabilities = FNAME_BCMSDCBUS(BCMMMIOReadLong)(SDHCI_CAPABILITIES, __BCM2708Bus);
__BCM2708Bus->sdcb_Quirks = AB_Quirk_MissingCapabilities|AF_Quirk_AtomicTMAndCMD;
Expand All @@ -273,6 +296,32 @@ static int FNAME_BCMSDC(BCM2708Init)(struct SDCardBase *SDCardBase)
DINIT(bug("[SDCard--] %s: SDHCI Capabilities : 0x%08x\n", __PRETTY_FUNCTION__, __BCM2708Bus->sdcb_Capabilities));
DINIT(bug("[SDCard--] %s: SDHCI Voltages : 0x%08x (hardcoded)\n", __PRETTY_FUNCTION__, __BCM2708Bus->sdcb_Power));

/*
* The mailbox reports what the clock could be turned up to, which
* is not what the divider divides. The controller knows its own
* base clock, so believe that instead: on the BCM2711 the mailbox
* says 500MHz while the block actually runs off 100MHz, and using
* the wrong one clocks the card five times too slowly.
*/
{
ULONG sdcClockBase;

if ((__BCM2708Bus->sdcb_Version & SDHCI_HVERS_SPEC_MASK) >= 2)
sdcClockBase = (__BCM2708Bus->sdcb_Capabilities & SDHCI_CLOCK_V3_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
else
sdcClockBase = (__BCM2708Bus->sdcb_Capabilities & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;

if (sdcClockBase)
__BCM2708Bus->sdcb_ClockMax = sdcClockBase * 1000000;
else
DINIT(bug("[SDCard--] %s: controller reports no base clock, keeping the mailbox rate\n", __PRETTY_FUNCTION__));
}

DINIT(bug("[SDCard--] %s: SDHC Base Clock Rate : %dMHz\n", __PRETTY_FUNCTION__, __BCM2708Bus->sdcb_ClockMax / 1000000));
DINIT(bug("[SDCard--] %s: SDHC Min Clock Rate : %dHz (hardcoded)\n", __PRETTY_FUNCTION__, __BCM2708Bus->sdcb_ClockMin));

FNAME_SDCBUS(ADMAAlloc)(__BCM2708Bus);

__BCM2708Bus->sdcb_Private = (IPTR)sdcard_CurrentTime();

FNAME_SDC(RegisterBus)(__BCM2708Bus, SDCardBase);
Expand Down
Loading
Loading