arm:mmc driver small cleanup.
This commit is contained in:
parent
401bad1a4d
commit
8ce3150cd6
|
|
@ -39,28 +39,27 @@ struct mmc_host;
|
|||
|
||||
struct sd_card_regs
|
||||
{
|
||||
uint32_t cid[4]; /* Card Identification */
|
||||
uint32_t rca; /* Relative card address */
|
||||
uint32_t dsr; /* Driver stage register */
|
||||
uint32_t csd[4]; /* Card specific data */
|
||||
uint32_t scr[2]; /* SD configuration */
|
||||
uint32_t ocr; /* Operation conditions */
|
||||
uint32_t ssr[5]; /* SD Status */
|
||||
uint32_t csr; /* Card status */
|
||||
uint32_t cid[4]; /* Card Identification */
|
||||
uint32_t rca; /* Relative card address */
|
||||
uint32_t dsr; /* Driver stage register */
|
||||
uint32_t csd[4]; /* Card specific data */
|
||||
uint32_t scr[2]; /* SD configuration */
|
||||
uint32_t ocr; /* Operation conditions */
|
||||
uint32_t ssr[5]; /* SD Status */
|
||||
uint32_t csr; /* Card status */
|
||||
};
|
||||
|
||||
#define RESP_LEN_48_CHK_BUSY (3<<0)
|
||||
#define RESP_LEN_48 (2<<0)
|
||||
#define RESP_LEN_136 (1<<0)
|
||||
#define NO_RESPONSE (0<<0)
|
||||
|
||||
/* struct representing an mmc command */
|
||||
struct mmc_command
|
||||
{
|
||||
uint32_t cmd;
|
||||
uint32_t args;
|
||||
uint32_t resp_type;
|
||||
|
||||
#define RESP_LEN_48_CHK_BUSY (3<<0)
|
||||
#define RESP_LEN_48 (2<<0)
|
||||
#define RESP_LEN_136 (1<<0)
|
||||
#define NO_RESPONSE (0<<0)
|
||||
|
||||
uint32_t resp[4];
|
||||
unsigned char *data;
|
||||
uint32_t data_len;
|
||||
|
|
|
|||
|
|
@ -43,6 +43,11 @@ static int hook_id = 1;
|
|||
|
||||
#define SANE_TIMEOUT 500000 /* 500 ms */
|
||||
|
||||
/* Integer divide x by y and ensure that the result z is
|
||||
* such that x / z is smaller or equal y
|
||||
*/
|
||||
#define div_roundup(x, y) (((x)+((y)-1))/(y))
|
||||
|
||||
/*
|
||||
* Define a structure to be used for logging
|
||||
*/
|
||||
|
|
@ -52,8 +57,33 @@ static struct log log = {
|
|||
.log_func = default_log
|
||||
};
|
||||
|
||||
/**
|
||||
* MMC use memory mapped IO and base_address is the
|
||||
* base address for the controller in use.
|
||||
*/
|
||||
static uint32_t base_address;
|
||||
|
||||
#define HSMMCSD_0_IN_FREQ 96000000 /* 96MHz */
|
||||
#define HSMMCSD_0_INIT_FREQ 400000 /* 400kHz */
|
||||
#define HSMMCSD_0_FREQ_25MHZ 25000000 /* 25MHz */
|
||||
#define HSMMCSD_0_FREQ_50MHZ 50000000 /* 50MHz */
|
||||
|
||||
int
|
||||
mmchs_set_bus_freq(u32_t freq)
|
||||
{
|
||||
u32_t freq_in = HSMMCSD_0_IN_FREQ;
|
||||
u32_t freq_out = freq;
|
||||
|
||||
/* Calculate and program the divisor */
|
||||
u32_t clkd = div_roundup(freq_in,freq_out);
|
||||
clkd = (clkd < 2) ? 2 : clkd;
|
||||
clkd = (clkd > 1023) ? 1023 : clkd;
|
||||
|
||||
log_debug(&log,"Setting divider to %d\n",clkd);
|
||||
set32(base_address + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_CLKD,
|
||||
(clkd << 6));
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the MMC controller given a certain
|
||||
* instance. this driver only handles a single
|
||||
|
|
@ -69,19 +99,24 @@ mmchs_init(uint32_t instance)
|
|||
spin_t spin;
|
||||
|
||||
mr.mr_base = MMCHS1_REG_BASE;
|
||||
mr.mr_limit = MMCHS1_REG_BASE + 0x400;
|
||||
mr.mr_limit = MMCHS1_REG_BASE + MMCHS1_REG_BASE_SIZE;
|
||||
|
||||
/* grant ourself rights to map the register memory */
|
||||
if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != 0) {
|
||||
panic("Unable to request permission to map memory");
|
||||
}
|
||||
|
||||
/* Set the base address to use */
|
||||
base_address =
|
||||
(uint32_t) vm_map_phys(SELF, (void *) MMCHS1_REG_BASE, 0x400);
|
||||
(uint32_t) vm_map_phys(SELF, (void *) MMCHS1_REG_BASE, MMCHS1_REG_BASE_SIZE);
|
||||
|
||||
if (base_address == (uint32_t) MAP_FAILED)
|
||||
panic("Unable to map MMC memory");
|
||||
|
||||
#ifdef DM37XX
|
||||
/* DM and AM have the same register but shifted by 0x100. instead of redefining the registers
|
||||
* we simply move the start offset
|
||||
*/
|
||||
base_address = (unsigned long) base_address - 0x100;
|
||||
#endif
|
||||
|
||||
|
|
@ -139,7 +174,8 @@ mmchs_init(uint32_t instance)
|
|||
* MMC host and bus configuration
|
||||
*/
|
||||
|
||||
/* Configure data and command transfer (1 bit mode) */
|
||||
/* Configure data and command transfer (1 bit mode) switching
|
||||
* to higher bit modes happens after a card is detected */
|
||||
set32(base_address + MMCHS_SD_CON, MMCHS_SD_CON_DW8,
|
||||
MMCHS_SD_CON_DW8_1BIT);
|
||||
set32(base_address + MMCHS_SD_HCTL, MMCHS_SD_HCTL_DTW,
|
||||
|
|
@ -154,7 +190,6 @@ mmchs_init(uint32_t instance)
|
|||
set32(base_address + MMCHS_SD_HCTL, MMCHS_SD_HCTL_SDBP,
|
||||
MMCHS_SD_HCTL_SDBP_ON);
|
||||
|
||||
// /* TODO: Add padconf/pinmux stuff here as documented in the TRM */
|
||||
spin_init(&spin, SANE_TIMEOUT);
|
||||
while ((read32(base_address + MMCHS_SD_HCTL) & MMCHS_SD_HCTL_SDBP)
|
||||
!= MMCHS_SD_HCTL_SDBP_ON) {
|
||||
|
|
@ -168,12 +203,8 @@ mmchs_init(uint32_t instance)
|
|||
set32(base_address + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_ICE,
|
||||
MMCHS_SD_SYSCTL_ICE_EN);
|
||||
|
||||
// @TODO Fix external clock enable , this one is very slow
|
||||
// but we first need faster context switching
|
||||
// set32(base_address + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_CLKD,
|
||||
// (0x20 << 6));
|
||||
set32(base_address + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_CLKD,
|
||||
(0x2 << 6));
|
||||
mmchs_set_bus_freq(HSMMCSD_0_INIT_FREQ);
|
||||
|
||||
|
||||
set32(base_address + MMCHS_SD_SYSCTL, MMCHS_SD_SYSCTL_CEN,
|
||||
MMCHS_SD_SYSCTL_CEN_EN);
|
||||
|
|
@ -247,7 +278,7 @@ mmchs_init(uint32_t instance)
|
|||
#ifdef USE_INTR
|
||||
hook_id = 1;
|
||||
if (sys_irqsetpolicy(OMAP3_MMC1_IRQ, 0, &hook_id) != OK) {
|
||||
printf("mmc: couldn't set IRQ policy %d\n", OMAP3_MMC1_IRQ);
|
||||
log_warn(&log,"mmc: couldn't set IRQ policy %d\n", OMAP3_MMC1_IRQ);
|
||||
return 1;
|
||||
}
|
||||
/* enable signaling from MMC controller towards interrupt controller */
|
||||
|
|
@ -280,7 +311,7 @@ handle_bwr()
|
|||
/* handle buffer write ready interrupts. These happen in a non
|
||||
* predictable way (eg. we send a request but don't know if we are
|
||||
* first doing to get a request completed before we are allowed to
|
||||
* send the data to the harware or not */
|
||||
* send the data to the hardware or not */
|
||||
uint32_t value;
|
||||
uint32_t count;
|
||||
assert(read32(base_address +
|
||||
|
|
@ -392,7 +423,7 @@ intr_wait(int mask)
|
|||
/* this is the normal return
|
||||
* path, the mask given
|
||||
* matches the pending
|
||||
* interrupt. canel the alarm
|
||||
* interrupt. cancel the alarm
|
||||
* and return */
|
||||
sys_setalarm(0, 0);
|
||||
return 0;
|
||||
|
|
@ -415,14 +446,14 @@ intr_wait(int mask)
|
|||
break;
|
||||
default:
|
||||
/*
|
||||
* unhandled message. queue it and
|
||||
* unhandled notify message. Queue it and
|
||||
* handle it in the blockdriver loop.
|
||||
*/
|
||||
blockdriver_mq_queue(&m, ipc_status);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* unhandled message. queue it and handle it in the
|
||||
* unhandled message. Queue it and handle it in the
|
||||
* blockdriver loop.
|
||||
*/
|
||||
blockdriver_mq_queue(&m, ipc_status);
|
||||
|
|
@ -698,7 +729,7 @@ card_query_voltage_and_type(struct sd_card_regs *card)
|
|||
if (mmc_send_app_cmd(card, &command)) {
|
||||
return 1;
|
||||
}
|
||||
/* @todo wait for max 1 ms */
|
||||
|
||||
spin_init(&spin, SANE_TIMEOUT);
|
||||
while (!(command.resp[0] & MMC_OCR_MEM_READY)) {
|
||||
|
||||
|
|
@ -790,9 +821,6 @@ card_csd(struct sd_card_regs *card)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* sanity check */
|
||||
// log_warn(&log,"size = %llu bytes\n", (long long
|
||||
// unsigned)SD_CSD_V2_CAPACITY( card->csd) * 512);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -836,7 +864,7 @@ card_scr(struct sd_card_regs *card)
|
|||
|
||||
p = (uint8_t *) card->scr;
|
||||
|
||||
/* hussle */
|
||||
/* copy the data to card->scr */
|
||||
for (c = 7; c >= 0; c--) {
|
||||
*p++ = buffer[c];
|
||||
}
|
||||
|
|
@ -875,7 +903,35 @@ enable_4bit_mode(struct sd_card_regs *card)
|
|||
/* now configure the controller to use 4 bit access */
|
||||
set32(base_address + MMCHS_SD_HCTL, MMCHS_SD_HCTL_DTW,
|
||||
MMCHS_SD_HCTL_DTW_4BIT);
|
||||
return 0;
|
||||
}
|
||||
return 1; /* expect 4 bits mode to work so having a card
|
||||
that doesn't support 4 bits mode */
|
||||
}
|
||||
|
||||
int
|
||||
enable_high_speed_mode(struct sd_card_regs *card)
|
||||
{
|
||||
/* MMC cards using version 4.0 or higher of the specs can work
|
||||
* at higher bus rates. After setting the bus width one can
|
||||
* send the HS_TIMING command to set the card in high speed
|
||||
* mode after witch one can higher up the frequency
|
||||
*/
|
||||
log_info(&log,
|
||||
"Enabling high speed mode\n");
|
||||
|
||||
if (SD_CSD_SPEED(card->csd) == SD_CSD_SPEED_25_MHZ) {
|
||||
log_trace(&log,
|
||||
"Using 25MHz clock\n");
|
||||
mmchs_set_bus_freq(HSMMCSD_0_FREQ_25MHZ);
|
||||
} else if (SD_CSD_SPEED(card->csd) == SD_CSD_SPEED_50_MHZ) {
|
||||
log_trace(&log,
|
||||
"Using 50MHz clock\n");
|
||||
mmchs_set_bus_freq(HSMMCSD_0_FREQ_50MHZ);
|
||||
} else {
|
||||
log_warn(&log,"Unknown speed 0x%x in CSD register\n",SD_CSD_SPEED(card->csd));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -983,6 +1039,7 @@ mmchs_card_initialize(struct sd_slot *slot)
|
|||
log_warn(&log, "Failed to do card_query_voltage_and_type\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (card_identify(&slot->card.regs)) {
|
||||
log_warn(&log, "Failed to identify card\n");
|
||||
return NULL;
|
||||
|
|
@ -1009,6 +1066,11 @@ mmchs_card_initialize(struct sd_slot *slot)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if(enable_high_speed_mode(&slot->card.regs)){
|
||||
log_warn(&log, "failed to configure high speed mode mode\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (SD_CSD_READ_BL_LEN(slot->card.regs.csd) != 0x09) {
|
||||
/* for CSD version 2.0 the value is fixed to 0x09 and means a
|
||||
* block size of 512 */
|
||||
|
|
@ -1020,6 +1082,7 @@ mmchs_card_initialize(struct sd_slot *slot)
|
|||
slot->card.blk_count = SD_CSD_V2_CAPACITY(slot->card.regs.csd);
|
||||
slot->card.state = SD_MODE_DATA_TRANSFER_MODE;
|
||||
|
||||
/* MINIX related stuff to keep track of partitions */
|
||||
memset(slot->card.part, 0, sizeof(slot->card.part));
|
||||
memset(slot->card.subpart, 0, sizeof(slot->card.subpart));
|
||||
slot->card.part[0].dv_base = 0;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@
|
|||
#ifdef DM37XX
|
||||
#define MMCHS1_REG_BASE 0x4809C000
|
||||
#endif
|
||||
|
||||
/* The size of the memory mapped register */
|
||||
#define MMCHS1_REG_BASE_SIZE 0x2ff
|
||||
//#define MMCHS2_REG_BASE 0x480B4000
|
||||
//#define MMCHS3_REG_BASE 0x480AD000
|
||||
//#endif
|
||||
|
|
|
|||
|
|
@ -308,6 +308,7 @@
|
|||
#define SCR_SD_BUS_WIDTHS(scr) MMC_RSP_BITS((scr), 48, 4)
|
||||
#define SCR_SD_BUS_WIDTHS_1BIT (1 << 0) /* 1bit (DAT0) */
|
||||
#define SCR_SD_BUS_WIDTHS_4BIT (1 << 2) /* 4bit (DAT0-3) */
|
||||
#define SCR_SD_SPEC3(scr) MMC_RSP_BITS((scr), 47, 1)
|
||||
#define SCR_RESERVED(scr) MMC_RSP_BITS((scr), 32, 16)
|
||||
#define SCR_RESERVED2(scr) MMC_RSP_BITS((scr), 0, 32)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user