eMMC: add support to 8-bit mode.

Change-Id: I0470130eb5f8de319cd55c448a9aa1b9131e8e07
This commit is contained in:
Leonardo Fogel 2015-07-02 18:45:04 -03:00 committed by David van Moolenbroek
parent 3e07920fe2
commit 4796287659
3 changed files with 57 additions and 14 deletions

View file

@ -742,6 +742,7 @@ service emmc
system
PRIVCTL
IRQCTL
PADCONF
;
irq
28 # MMCSD1INT

View file

@ -48,12 +48,22 @@
/* The card sector size is 512B. */
#define SEC_SIZE 512
/*
* AM335x Control Module registers CONF_GPMC_ADn.
* Configuration do multiplex CONF_GPMC_ADn to signals MMC1_DATn (Mode 1).
*/
#define CONF_GPMC_AD(N) (0x800 + 4*(N))
#define CONF_GPMC_AD_MASK 0x7F
#define CONF_GPMC_AD_VAL 0x31
/* AM335x MMC1 memory map (physical start address and size). */
#define AM335X_MMC1_BASE_ADDR 0x481D8000
#define AM335X_MMC1_SIZE (4 << 10)
/* AM335x MMC1 interrupt number. */
#define AM335X_MMCSD1INT 28
static uint32_t bus_width;
/* AM335x MMCHS registers virtual addresses: virtual base + offset. */
static struct omap_mmchs_registers *reg;
@ -439,8 +449,8 @@ read_busy(void)
{
uint32_t stat;
/*
* The busy signal is optional, but the host controller will assert
* SD_STAT[1] TC even if the card does not send it.
* The busy signal is optional, but the host controller will assert
* SD_STAT[1] TC even if the card does not send it.
*/
if (irq_wait() < 0)
return -1;
@ -619,6 +629,24 @@ minix_init(void)
return 0;
}
/*
* Configure the Control Module registers CONF_GPMC_AD4-7.
* Multiplex pins GPMC_AD4-7 to signals MMC1_DAT4-7 (Mode 1).
* Return 0 on success, a negative integer on error.
*/
static int
conf_gpmc_ad(void)
{
uint32_t i;
for (i=4; i<8; i++) {
if (sys_padconf(CONF_GPMC_AD(i), CONF_GPMC_AD_MASK,
CONF_GPMC_AD_VAL) != OK)
return -1;
}
return 0;
}
/*
* Interface to the MINIX block device driver.
* Host controller initialization.
@ -638,6 +666,16 @@ emmc_host_init(struct mmc_host *host)
if (minix_init() < 0)
return -1;
/*
* Multiplex pins GPMC_AD4-7 to signals MMC1_DAT4-7 (Mode 1), in order
* to allow the use of 8-bit mode.
* U-Boot multiplexes only pins GPMC_AD0-3 to signals MMC1_DAT0-3.
*/
if (conf_gpmc_ad() < 0)
bus_width = EXT_CSD_BUS_WIDTH_4;
else
bus_width = EXT_CSD_BUS_WIDTH_8;
/* Reset the host controller. */
set32(reg->SYSCONFIG, MMCHS_SD_SYSCONFIG_SOFTRESET,
MMCHS_SD_SYSCONFIG_SOFTRESET);
@ -676,7 +714,7 @@ emmc_host_init(struct mmc_host *host)
/* Enable the bus clock. */
set32(reg->SYSCTL, MMCHS_SD_SYSCTL_CEN, MMCHS_SD_SYSCTL_CEN_EN);
/*
* Set the internal clock gating strategy to automatic, and enable
* Smart Idle mode. The host controller does not implement wake-up
@ -810,7 +848,7 @@ emmc_card_initialize(struct sd_slot *slot)
/* Card capacity for densities greater than 2GB. */
if (MMC_EXT_CSD_SEC_COUNT > 0)
card_size = (uint64_t)MMC_EXT_CSD_SEC_COUNT * SEC_SIZE;
/* CMD6. Switch to high-speed mode: EXT_CSD[185] HS_TIMING = 1. */
if (mmc_switch(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_HS_TIMING, 1) < 0)
return NULL;
@ -832,9 +870,9 @@ emmc_card_initialize(struct sd_slot *slot)
/* Set data and busy time-out: ~ 2,8s @ 48MHz.*/
set32(reg->SYSCTL, MMCHS_SD_SYSCTL_DTO, MMCHS_SD_SYSCTL_DTO_2POW27);
/* CMD6. Set data bus width to 4. */
/* CMD6. Set data bus width. */
if (mmc_switch(MMC_SWITCH_MODE_WRITE_BYTE, EXT_CSD_BUS_WIDTH,
EXT_CSD_BUS_WIDTH_4) < 0)
bus_width) < 0)
return NULL;
/* Wait for the (optional) busy signal. */
if (read_busy() < 0)
@ -843,8 +881,11 @@ emmc_card_initialize(struct sd_slot *slot)
if (send_status() < 0)
return NULL;
/* Host controller: set 4-bit data bus width. */
set32(reg->HCTL, MMCHS_SD_HCTL_DTW, MMCHS_SD_HCTL_DTW_4BIT);
/* Host controller: set data bus width. */
if (bus_width == EXT_CSD_BUS_WIDTH_4)
set32(reg->HCTL, MMCHS_SD_HCTL_DTW, MMCHS_SD_HCTL_DTW_4BIT);
else
set32(reg->CON, MMCHS_SD_CON_DW8, MMCHS_SD_CON_DW8_8BITS);
/* CMD16. Set block length to sector size (512B). */
if (set_blocklen() < 0)

View file

@ -1,17 +1,18 @@
The eMMC driver was designed to be linked to the existing MMC/SD block device driver (mmcblk.c).
The eMMC driver was designed to be linked to the existing MMC/SD block device
driver (mmcblk.c).
* Mini how-to
On the BeagleBone Black, the block device files /dev/c1d* (major = 8) are free. The driver can use /dev/c1d0.
On the BeagleBone Black, the block device files /dev/c1d* (major = 8) are free.
The driver can use /dev/c1d0.
# service up /service/emmc -dev /dev/c1d0
* 4-bit mode (data bus width)
On the BeagleBone Black, the eMMC data lines are connected to the AM335x GPMC_AD[0-7] pins. After PoR, these pins are multiplexed to signals GPIO1_[0-7], and U-Boot only multiplexes pins GPMC_AD[0-3] to signals MMC1_DAT[0-3]. Consequently, 8-bit mode (signals MMC1_DAT[4-7]) can not be used.
* Programmed Input/Output
The driver does not have support for DMA.
* High capacity cards
Data address for media =< 2GB is byte address, and data address for media > 2GB is sector (512B) address. The driver was designed to handle both address modes, but it was tested on a 2GB card.
Data address for media =< 2GB is byte address, and data address for media > 2GB
is sector (512B) address. The driver was designed to handle both address modes,
but it was tested on a 2GB card.
* References
BeagleBone Black System Reference Manual, Revision A5.6.