ARM: MMC driver
- Simplify build structure & Makefiles - Fix log system, by making sure there is only one log object per driver and fixed level management, to be able to set LEVEL_TRACE - Fixed block size support on RPI, as the MMC driver uses different block sizes
This commit is contained in:
@@ -1,4 +1,17 @@
|
||||
.include <bsd.own.mk>
|
||||
SUBDIR+= rpi omap
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
.for pl in omap rpi
|
||||
PROGS += ${pl}_mmc ${pl}_emmc
|
||||
MAN.${pl}_emmc =
|
||||
MAN.${pl}_mmc =
|
||||
|
||||
SRCS.${pl}_emmc += mmcblk.c emmc_${pl}.c
|
||||
SRCS.${pl}_mmc += mmcblk.c mmchost_dummy.c mmchost_${pl}.c
|
||||
.endfor
|
||||
|
||||
BINDIR= /service/
|
||||
|
||||
DPADD+= ${LIBBLOCKDRIVER} ${LIBSYS}
|
||||
LDADD+= -lblockdriver -lsys
|
||||
|
||||
.include <minix.service.mk>
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
HERE=${.CURDIR}/..
|
||||
.PATH: ${HERE}
|
||||
|
||||
MMC_SRCS= mmcblk.c mmchost_dummy.c sdhcreg.h sdmmcreg.h
|
||||
@@ -7,9 +7,9 @@
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "omap_mmc.h"
|
||||
#include "../mmchost.h"
|
||||
#include "../sdmmcreg.h"
|
||||
#include "mmc_omap.h"
|
||||
#include "mmchost.h"
|
||||
#include "sdmmcreg.h"
|
||||
|
||||
/* MINIX IRQ timeout. Twice the host controller data/busy timeout @ 48MHz. */
|
||||
#define IRQ_TIMEOUT 5600000 /* 5,600,000 us */
|
||||
@@ -77,14 +77,6 @@ static uint64_t card_size;
|
||||
/* IRQ_HOOK_ID for SYS_IRQCTL kernel call. */
|
||||
static int hook_id = 1;
|
||||
|
||||
/* Initialize the log system. */
|
||||
static struct log log = {
|
||||
.name = "emmc",
|
||||
.log_level = LEVEL_INFO,
|
||||
.log_func = default_log,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Spin until a register flag is set, or the time runs out.
|
||||
* Return the flag value.
|
||||
@@ -223,8 +215,10 @@ send_cmd(uint32_t arg, uint32_t cmd)
|
||||
write32(reg->ARG, arg);
|
||||
write32(reg->CMD, cmd);
|
||||
/* Wait for the command completion. */
|
||||
if (irq_wait() < 0)
|
||||
if (irq_wait() < 0) {
|
||||
log_warn (&log, "can't wait irq\n");
|
||||
return -1;
|
||||
}
|
||||
stat = read32(reg->SD_STAT);
|
||||
/*
|
||||
* Clear only the command status/error bits. The transfer status/error
|
||||
@@ -236,6 +230,7 @@ send_cmd(uint32_t arg, uint32_t cmd)
|
||||
| MMCHS_SD_STAT_CTO
|
||||
| MMCHS_SD_STAT_CC);
|
||||
if (stat & MMCHS_SD_STAT_CTO) {
|
||||
log_warn(&log, "timeout error\n");
|
||||
reset_mmchs_fsm(MMCHS_SD_SYSCTL_SRC);
|
||||
return -1;
|
||||
}
|
||||
@@ -623,8 +618,10 @@ minix_init(void)
|
||||
reg->ISE += v_base;
|
||||
|
||||
/* Register the MMC1 interrupt number. */
|
||||
if (sys_irqsetpolicy(AM335X_MMCSD1INT, 0, &hook_id) != OK)
|
||||
if (sys_irqsetpolicy(AM335X_MMCSD1INT, 0, &hook_id) != OK) {
|
||||
log_warn(&log, "can't set irq\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -743,17 +740,6 @@ emmc_host_init(struct mmc_host *host)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Interface to the MINIX block device driver.
|
||||
* Set the log level.
|
||||
*/
|
||||
static void
|
||||
emmc_set_log_level(int level)
|
||||
{
|
||||
log.log_level = level;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Interface to the MINIX block device driver.
|
||||
* Unused, but declared in mmchost.h.
|
||||
@@ -841,6 +827,7 @@ emmc_card_initialize(struct sd_slot *slot)
|
||||
/* CMD8 */
|
||||
if (send_ext_csd() < 0)
|
||||
return NULL;
|
||||
|
||||
/* Receive the Extended CSD register. */
|
||||
if (read_data((uint32_t *)card_ext_csd) < 0)
|
||||
return NULL;
|
||||
@@ -1005,7 +992,6 @@ host_initialize_host_structure_mmchs(struct mmc_host *host)
|
||||
/* Register the driver interface at the block device driver. */
|
||||
host->host_set_instance = &emmc_host_set_instance;
|
||||
host->host_init = &emmc_host_init;
|
||||
host->set_log_level = &emmc_set_log_level;
|
||||
host->host_reset = NULL;
|
||||
host->card_detect = &emmc_card_detect;
|
||||
host->card_initialize = &emmc_card_initialize;
|
||||
@@ -1018,6 +1004,9 @@ host_initialize_host_structure_mmchs(struct mmc_host *host)
|
||||
host->slot[i].card.state = SD_MODE_UNINITIALIZED;
|
||||
host->slot[i].card.slot = &host->slot[i];
|
||||
}
|
||||
|
||||
/* Customize name for logs */
|
||||
log.name = "emmc_omap";
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1027,4 +1016,4 @@ host_initialize_host_structure_mmchs(struct mmc_host *host)
|
||||
void
|
||||
host_initialize_host_structure_dummy(struct mmc_host *host)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -6,10 +6,10 @@
|
||||
#include <minix/syslib.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
//#include "rpi_mmc.h"
|
||||
#include "../mmchost.h"
|
||||
#include "../sdmmcreg.h"
|
||||
#include "rpi_mmc.h"
|
||||
|
||||
#include "mmc_rpi.h"
|
||||
#include "mmchost.h"
|
||||
#include "sdmmcreg.h"
|
||||
|
||||
/* MINIX IRQ timeout. Twice the host controller data/busy timeout @ 48MHz. */
|
||||
#define IRQ_TIMEOUT 5600000 /* 5,600,000 us */
|
||||
@@ -65,7 +65,7 @@
|
||||
static uint32_t bus_width;
|
||||
|
||||
/* AM335x MMCHS registers virtual addresses: virtual base + offset. */
|
||||
static rpi_mmchs_registers *reg;
|
||||
static struct rpi_mmchs_registers *reg;
|
||||
|
||||
/* Card registers. */
|
||||
static uint32_t card_csd[4];
|
||||
@@ -77,14 +77,6 @@ static uint64_t card_size;
|
||||
/* IRQ_HOOK_ID for SYS_IRQCTL kernel call. */
|
||||
static int hook_id = 1;
|
||||
|
||||
/* Initialize the log system. */
|
||||
static struct log log = {
|
||||
.name = "emmc",
|
||||
.log_level = LEVEL_INFO,
|
||||
.log_func = default_log,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Spin until a register flag is set, or the time runs out.
|
||||
* Return the flag value.
|
||||
@@ -146,7 +138,6 @@ spin_until_clear(uint32_t address, uint32_t flag)
|
||||
static int
|
||||
set_bus_clkd(uint32_t clkd)
|
||||
{
|
||||
uint32_t control1;
|
||||
/*
|
||||
* Disable the bus clock, set the clock divider, wait until the
|
||||
* internal clock is stable, enable the bus clock.
|
||||
@@ -258,6 +249,7 @@ send_cmd(uint32_t arg, uint32_t cmd)
|
||||
reset_mmchs_fsm(MMCHS_SD_SYSCTL_SRC);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -273,6 +265,7 @@ send_cmd_check_r1(uint32_t arg, uint32_t cmd)
|
||||
/* Check for card errors in the card response (R1). */
|
||||
if (read32(reg->resp0) & R1_ERROR_MASK)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -532,6 +525,7 @@ write_data(uint32_t *data)
|
||||
reset_mmchs_fsm(MMCHS_SD_SYSCTL_SRD);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -623,6 +617,7 @@ minix_init(void)
|
||||
log_warn(&log, "can't set irq\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -701,29 +696,21 @@ emmc_host_init(struct mmc_host *host)
|
||||
| MMCHS_SD_IE_BWR_ENABLE_ENABLE
|
||||
| MMCHS_SD_IE_TC_ENABLE_ENABLE
|
||||
| MMCHS_SD_IE_CC_ENABLE_ENABLE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Interface to the MINIX block device driver.
|
||||
* Set the log level.
|
||||
*/
|
||||
static void
|
||||
emmc_set_log_level(int level)
|
||||
{
|
||||
log.log_level = level;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Interface to the MINIX block device driver.
|
||||
* Unused, but declared in mmchost.h.
|
||||
*/
|
||||
#if 0
|
||||
static int
|
||||
emmc_host_reset(struct mmc_host *host)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Interface to the MINIX block device driver.
|
||||
@@ -856,6 +843,7 @@ emmc_card_release(struct sd_card *card)
|
||||
* The block special file is closed, but the driver does not need to
|
||||
* "release" the eMMC, even if the driver is unloaded.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -931,6 +919,10 @@ emmc_write(struct sd_card *card,
|
||||
return emmc_read_write(&cim_write_block, blknr, count, buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Interface to the MINIX block device driver.
|
||||
* Driver interface registration.
|
||||
*/
|
||||
void
|
||||
host_initialize_host_structure_mmchs(struct mmc_host *host)
|
||||
{
|
||||
@@ -939,7 +931,6 @@ host_initialize_host_structure_mmchs(struct mmc_host *host)
|
||||
/* Register the driver interface at the block device driver. */
|
||||
host->host_set_instance = &emmc_host_set_instance;
|
||||
host->host_init = &emmc_host_init;
|
||||
host->set_log_level = &emmc_set_log_level;
|
||||
host->host_reset = NULL;
|
||||
host->card_detect = &emmc_card_detect;
|
||||
host->card_initialize = &emmc_card_initialize;
|
||||
@@ -952,6 +943,9 @@ host_initialize_host_structure_mmchs(struct mmc_host *host)
|
||||
host->slot[i].card.state = SD_MODE_UNINITIALIZED;
|
||||
host->slot[i].card.slot = &host->slot[i];
|
||||
}
|
||||
|
||||
/* Customize name for logs */
|
||||
log.name = "emmc_rpi";
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -961,4 +955,4 @@ host_initialize_host_structure_mmchs(struct mmc_host *host)
|
||||
void
|
||||
host_initialize_host_structure_dummy(struct mmc_host *host)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,5 @@
|
||||
struct omap_mmchs_registers;
|
||||
|
||||
struct omap_mmchs {
|
||||
vir_bytes io_base;
|
||||
vir_bytes io_size;
|
||||
phys_bytes hw_base;/* HW address */
|
||||
int irq_nr;
|
||||
struct omap_mmchs_registers * regs;
|
||||
};
|
||||
#ifndef _MMC_OMAP_H_
|
||||
#define _MMC_OMAP_H_
|
||||
|
||||
struct omap_mmchs_registers {
|
||||
/* SD system configuration */
|
||||
@@ -51,8 +44,16 @@ struct omap_mmchs_registers {
|
||||
vir_bytes CUR_CAPA;
|
||||
};
|
||||
|
||||
struct omap_mmchs {
|
||||
vir_bytes io_base;
|
||||
vir_bytes io_size;
|
||||
phys_bytes hw_base;/* HW address */
|
||||
int irq_nr;
|
||||
struct omap_mmchs_registers * regs;
|
||||
};
|
||||
|
||||
/* version used on the AM335x */
|
||||
static struct omap_mmchs_registers regs_v1 = {
|
||||
struct omap_mmchs_registers regs_v1 = {
|
||||
.SYSCONFIG = 0x110,
|
||||
.SYSSTATUS = 0x114,
|
||||
.CON = 0x12c,
|
||||
@@ -77,7 +78,7 @@ static struct omap_mmchs_registers regs_v1 = {
|
||||
|
||||
/* version used on the DM37xx */
|
||||
/* DM and AM have the same register but shifted by 0x100. */
|
||||
static struct omap_mmchs_registers regs_v0 = {
|
||||
struct omap_mmchs_registers regs_v0 = {
|
||||
.SYSCONFIG = 0x010,
|
||||
.SYSSTATUS = 0x014,
|
||||
.CON = 0x02c,
|
||||
@@ -100,7 +101,6 @@ static struct omap_mmchs_registers regs_v0 = {
|
||||
.CUR_CAPA = 0x148,
|
||||
};
|
||||
|
||||
|
||||
#define MMCHS_SD_SYSCONFIG_AUTOIDLE (0x1 << 0) /* Internal clock gating strategy */
|
||||
#define MMCHS_SD_SYSCONFIG_AUTOIDLE_DIS (0x0 << 0) /* Clocks are free running */
|
||||
#define MMCHS_SD_SYSCONFIG_AUTOIDLE_EN (0x1 << 0) /* Automatic clock gating strategy */
|
||||
@@ -273,3 +273,4 @@ static struct omap_mmchs_registers regs_v0 = {
|
||||
#define MMCHS_SD_CAPA_VS30 (0x01 << 25 ) /* 3.0 volt */
|
||||
#define MMCHS_SD_CAPA_VS33 (0x01 << 24 ) /* 3.3 volt */
|
||||
|
||||
#endif /* _MMC_OMAP_H_*/
|
||||
@@ -1,10 +1,10 @@
|
||||
#ifndef __SD_H__
|
||||
#define __SD_H__
|
||||
#ifndef _MMC_RPI_H_
|
||||
#define _MMC_RPI_H_
|
||||
|
||||
#define RW
|
||||
#define R
|
||||
|
||||
typedef struct {
|
||||
struct rpi_mmchs_registers {
|
||||
RW vir_bytes blkscnt;
|
||||
RW vir_bytes arg1;
|
||||
RW vir_bytes cmdtm;
|
||||
@@ -21,9 +21,17 @@ typedef struct {
|
||||
RW vir_bytes irpt_en;
|
||||
RW vir_bytes control2;
|
||||
RW vir_bytes slotisr_var;
|
||||
} rpi_mmchs_registers;
|
||||
};
|
||||
|
||||
rpi_mmchs_registers regs_v0 = {
|
||||
struct rpi_mmchs {
|
||||
vir_bytes io_base;
|
||||
vir_bytes io_size;
|
||||
phys_bytes hw_base;/* HW address */
|
||||
int irq_nr;
|
||||
struct rpi_mmchs_registers * regs;
|
||||
};
|
||||
|
||||
struct rpi_mmchs_registers regs_v0 = {
|
||||
.blkscnt = 0x4,
|
||||
.arg1 = 0x8,
|
||||
.cmdtm = 0xc,
|
||||
@@ -41,15 +49,6 @@ rpi_mmchs_registers regs_v0 = {
|
||||
.control2 = 0x3c,
|
||||
.slotisr_var = 0xfc
|
||||
};
|
||||
|
||||
struct rpi_mmchs {
|
||||
vir_bytes io_base;
|
||||
vir_bytes io_size;
|
||||
phys_bytes hw_base;/* HW address */
|
||||
int irq_nr;
|
||||
rpi_mmchs_registers * regs;
|
||||
};
|
||||
|
||||
#define MMCHS_SD_SYSCONFIG_AUTOIDLE (0x1 << 0) /* Internal clock gating strategy */
|
||||
#define MMCHS_SD_SYSCONFIG_AUTOIDLE_DIS (0x0 << 0) /* Clocks are free running */
|
||||
#define MMCHS_SD_SYSCONFIG_AUTOIDLE_EN (0x1 << 0) /* Automatic clock gating strategy */
|
||||
@@ -244,4 +243,4 @@ struct rpi_mmchs {
|
||||
// Enable SDXC maximum performance mode
|
||||
#define SDXC_MAXIMUM_PERFORMANCE
|
||||
|
||||
#endif
|
||||
#endif /* _MMC_RPI_H_*/
|
||||
@@ -22,11 +22,11 @@
|
||||
/* local headers */
|
||||
#include "mmchost.h"
|
||||
|
||||
/* used for logging */
|
||||
static struct log log = {
|
||||
.name = "mmc_block",
|
||||
/* Initialize the log system. */
|
||||
struct log log = {
|
||||
.name = "mmc",
|
||||
.log_level = LEVEL_INFO,
|
||||
.log_func = default_log
|
||||
.log_func = default_log,
|
||||
};
|
||||
|
||||
/* holding the current host controller */
|
||||
@@ -114,10 +114,10 @@ apply_env()
|
||||
} else {
|
||||
log_warn(&log, "Unknown driver %s\n", driver);
|
||||
}
|
||||
/* Initialize the verbosity level. */
|
||||
v = 0;
|
||||
/* Initialize the verbosity level. */
|
||||
if (env_parse("log_level", "d", 0, &v, LEVEL_NONE,
|
||||
LEVEL_TRACE) == EP_SET) {
|
||||
LEVEL_TRACE + 1) == EP_SET) {
|
||||
set_log_level(v);
|
||||
}
|
||||
|
||||
@@ -641,14 +641,11 @@ get_slot(devminor_t minor)
|
||||
static void
|
||||
set_log_level(int level)
|
||||
{
|
||||
if (level < 0 || level >= 4) {
|
||||
if ((level < LEVEL_NONE) || (level > (LEVEL_TRACE + 1))) {
|
||||
return;
|
||||
}
|
||||
log_info(&log, "Setting verbosity level to %d\n", level);
|
||||
log.log_level = level;
|
||||
if (host.set_log_level) {
|
||||
host.set_log_level(level);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
#define SUBPARTITION_PER_PARTITION 4 /* 4 sub partitions per partition */
|
||||
#define PARTITONS_PER_DISK 4 /* 4 partitions per disk */
|
||||
#define MINOR_PER_DISK 1 /* one additional minor to point to */
|
||||
@@ -30,6 +29,7 @@
|
||||
|
||||
#define MAX_SD_SLOTS 4
|
||||
|
||||
extern struct log log;
|
||||
struct mmc_host;
|
||||
|
||||
//TODO Add more modes like INACTIVE STATE and such
|
||||
@@ -110,8 +110,6 @@ struct mmc_host
|
||||
int (*host_set_instance) (struct mmc_host * host, int instance);
|
||||
/* MMC host configuration */
|
||||
int (*host_init) (struct mmc_host * host);
|
||||
/* Set log level */
|
||||
void (*set_log_level) (int level);
|
||||
/* Host controller reset */
|
||||
int (*host_reset) (struct mmc_host * host);
|
||||
/* Card detection (binary yes/no) */
|
||||
|
||||
@@ -14,15 +14,6 @@
|
||||
#include "mmchost.h"
|
||||
#include "sdmmcreg.h"
|
||||
|
||||
/*
|
||||
* Define a structure to be used for logging
|
||||
*/
|
||||
static struct log log = {
|
||||
.name = "mmc_host_memory",
|
||||
.log_level = LEVEL_INFO,
|
||||
.log_func = default_log
|
||||
};
|
||||
|
||||
/* This is currently a dummy driver using an in-memory structure */
|
||||
#define DUMMY_SIZE_IN_BLOCKS 0xFFFFFu
|
||||
#define DUMMY_BLOCK_SIZE 512
|
||||
@@ -70,14 +61,6 @@ dummy_host_init(struct mmc_host *host)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
dummy_set_log_level(int level)
|
||||
{
|
||||
if (level >= 0 && level <= 4) {
|
||||
log.log_level = level;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
dummy_host_set_instance(struct mmc_host *host, int instance)
|
||||
{
|
||||
@@ -152,7 +135,6 @@ host_initialize_host_structure_dummy(struct mmc_host *host)
|
||||
|
||||
host->host_set_instance = dummy_host_set_instance;
|
||||
host->host_init = dummy_host_init;
|
||||
host->set_log_level = dummy_set_log_level;
|
||||
host->host_reset = dummy_host_reset;
|
||||
host->card_detect = dummy_card_detect;
|
||||
host->card_initialize = dummy_card_initialize;
|
||||
@@ -167,4 +149,7 @@ host_initialize_host_structure_dummy(struct mmc_host *host)
|
||||
host->slot[i].card.slot = &host->slot[i];
|
||||
}
|
||||
init_dummy_sdcard(&host->slot[0]);
|
||||
|
||||
/* Customize name for logs */
|
||||
log.name = "mmc_memory";
|
||||
}
|
||||
|
||||
@@ -21,14 +21,14 @@
|
||||
#include <unistd.h>
|
||||
|
||||
/* local headers */
|
||||
#include "../mmchost.h"
|
||||
#include "mmchost.h"
|
||||
|
||||
/* header imported from netbsd */
|
||||
#include "../sdmmcreg.h"
|
||||
#include "../sdhcreg.h"
|
||||
#include "sdmmcreg.h"
|
||||
#include "sdhcreg.h"
|
||||
|
||||
/* omap /hardware related */
|
||||
#include "omap_mmc.h"
|
||||
#include "mmc_omap.h"
|
||||
|
||||
#define USE_INTR
|
||||
|
||||
@@ -36,8 +36,6 @@
|
||||
static int hook_id = 1;
|
||||
#endif
|
||||
|
||||
#define USE_DMA
|
||||
|
||||
#define SANE_TIMEOUT 500000 /* 500 ms */
|
||||
|
||||
struct omap_mmchs *mmchs; /* pointer to the current mmchs */
|
||||
@@ -63,19 +61,10 @@ struct omap_mmchs bbxm_sdcard = {
|
||||
*/
|
||||
#define div_roundup(x, y) (((x)+((y)-1))/(y))
|
||||
|
||||
/*
|
||||
* Define a structure to be used for logging
|
||||
*/
|
||||
static struct log log = {
|
||||
.name = "mmc_host_mmchs",
|
||||
.log_level = LEVEL_INFO,
|
||||
.log_func = default_log
|
||||
};
|
||||
|
||||
#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 */
|
||||
#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 */
|
||||
|
||||
void
|
||||
mmc_set32(vir_bytes reg, u32_t mask, u32_t value)
|
||||
@@ -149,7 +138,7 @@ mmchs_init(uint32_t instance)
|
||||
|
||||
/* Write 1 to sysconfig[0] to trigger a reset */
|
||||
mmc_set32(mmchs->regs->SYSCONFIG, MMCHS_SD_SYSCONFIG_SOFTRESET,
|
||||
MMCHS_SD_SYSCONFIG_SOFTRESET);
|
||||
MMCHS_SD_SYSCONFIG_SOFTRESET);
|
||||
|
||||
/* Read sysstatus to know when it's done */
|
||||
|
||||
@@ -1076,14 +1065,6 @@ mmchs_host_init(struct mmc_host *host)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
mmchs_set_log_level(int level)
|
||||
{
|
||||
if (level >= 0 && level <= 4) {
|
||||
log.log_level = level;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
mmchs_host_set_instance(struct mmc_host *host, int instance)
|
||||
{
|
||||
@@ -1189,9 +1170,7 @@ static int
|
||||
mmchs_host_read(struct sd_card *card,
|
||||
uint32_t blknr, uint32_t count, unsigned char *buf)
|
||||
{
|
||||
uint32_t i;
|
||||
i = count;
|
||||
for (i = 0; i < count; i++) {
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
read_single_block(&card->regs, blknr + i,
|
||||
buf + (i * card->blk_size));
|
||||
}
|
||||
@@ -1248,7 +1227,6 @@ host_initialize_host_structure_mmchs(struct mmc_host *host)
|
||||
assert(mmchs);
|
||||
host->host_set_instance = mmchs_host_set_instance;
|
||||
host->host_init = mmchs_host_init;
|
||||
host->set_log_level = mmchs_set_log_level;
|
||||
host->host_reset = mmchs_host_reset;
|
||||
host->card_detect = mmchs_card_detect;
|
||||
host->card_initialize = mmchs_card_initialize;
|
||||
@@ -1263,4 +1241,7 @@ host_initialize_host_structure_mmchs(struct mmc_host *host)
|
||||
host->slot[i].host = host;
|
||||
host->slot[i].card.slot = &host->slot[i];
|
||||
}
|
||||
|
||||
/* Customize name for logs */
|
||||
log.name = "mmc_omap";
|
||||
}
|
||||
@@ -21,14 +21,14 @@
|
||||
#include <unistd.h>
|
||||
|
||||
/* local headers */
|
||||
#include "../mmchost.h"
|
||||
#include "mmchost.h"
|
||||
|
||||
/* header imported from netbsd */
|
||||
#include "../sdmmcreg.h"
|
||||
#include "../sdhcreg.h"
|
||||
#include "sdmmcreg.h"
|
||||
#include "sdhcreg.h"
|
||||
|
||||
/* rpi hardware related */
|
||||
#include "rpi_mmc.h"
|
||||
#include "mmc_rpi.h"
|
||||
|
||||
#define USE_INTR
|
||||
|
||||
@@ -53,19 +53,10 @@ struct rpi_mmchs rpi_sdcard = {
|
||||
*/
|
||||
#define div_roundup(x, y) (((x)+((y)-1))/(y))
|
||||
|
||||
/*
|
||||
* Define a structure to be used for logging
|
||||
*/
|
||||
static struct log log = {
|
||||
.name = "mmc_host_mmchs",
|
||||
.log_level = LEVEL_INFO,
|
||||
.log_func = default_log
|
||||
};
|
||||
|
||||
#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 */
|
||||
#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 */
|
||||
|
||||
void
|
||||
mmc_set32(vir_bytes reg, u32_t mask, u32_t value)
|
||||
@@ -140,7 +131,7 @@ mmchs_init(uint32_t instance)
|
||||
mmc_write32(mmchs->regs->control0, 0);
|
||||
mmc_write32(mmchs->regs->control2, 0);
|
||||
/* Write 1 to sysconfig[0] to trigger a reset */
|
||||
mmc_set32(mmchs->regs->control1, MMCHS_SD_SYSCTL_SRA,
|
||||
mmc_set32(mmchs->regs->control1, MMCHS_SD_SYSCTL_SRA,
|
||||
MMCHS_SD_SYSCTL_SRA);
|
||||
|
||||
/* Read sysstatus to know when it's done */
|
||||
@@ -316,7 +307,6 @@ intr_wait(int mask)
|
||||
message m;
|
||||
int ipc_status;
|
||||
int ticks = SANE_TIMEOUT * sys_hz() / 1000000;
|
||||
log_info(&log, "wait irpt with 0x%x\n", mmc_read32(mmchs->regs->irpt));
|
||||
|
||||
if (ticks <= 0)
|
||||
ticks = 1;
|
||||
@@ -338,10 +328,12 @@ intr_wait(int mask)
|
||||
mmc_read32(mmchs->regs->irpt)) !=
|
||||
0) {
|
||||
if (v & MMCHS_SD_IE_BWR_ENABLE) {
|
||||
log_info(&log, "MMCHS_SD_IE_BWR_ENABLE 0x%x\n", v & MMCHS_SD_IE_BWR_ENABLE);
|
||||
handle_bwr();
|
||||
continue;
|
||||
}
|
||||
if (v & MMCHS_SD_IE_BRR_ENABLE) {
|
||||
log_info(&log, "MMCHS_SD_IE_BRR_ENABLE 0x%x\n", v & MMCHS_SD_IE_BRR_ENABLE);
|
||||
handle_brr();
|
||||
continue;
|
||||
}
|
||||
@@ -355,6 +347,7 @@ intr_wait(int mask)
|
||||
sys_setalarm(0, 0);
|
||||
return 0;
|
||||
} else if (v & (1 << 15)) {
|
||||
log_info(&log, "MASK 0x%x 0x%x\n", (1 << 15), v & (1 << 15));
|
||||
return 1; /* error */
|
||||
}
|
||||
|
||||
@@ -534,6 +527,7 @@ mmc_send_cmd(struct mmc_command *c)
|
||||
assert(io_data != NULL);
|
||||
mmc_set32(mmchs->regs->blkscnt, MMCHS_SD_BLK_BLEN, io_len);
|
||||
}
|
||||
|
||||
ret = mmchs_send_cmd(cmd, arg);
|
||||
|
||||
if (cmd & MMCHS_SD_CMD_DP_DATA) {
|
||||
@@ -570,6 +564,7 @@ mmc_send_cmd(struct mmc_command *c)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* copy response into cmd->resp */
|
||||
switch (c->resp_type) {
|
||||
case RESP_LEN_48_CHK_BUSY:
|
||||
@@ -630,6 +625,8 @@ card_identification()
|
||||
command.args = MMCHS_SD_ARG_CMD8_VHS | MMCHS_SD_ARG_CMD8_CHECK_PATTERN;
|
||||
|
||||
if (mmc_send_cmd(&command)) {
|
||||
/* We currently only support 2.0, and 1.0 won't respond to
|
||||
* this request */
|
||||
log_warn(&log, "%s, non SDHC card inserted\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
@@ -896,8 +893,7 @@ mmc_switch(int function, int value, uint8_t * data)
|
||||
}
|
||||
|
||||
int
|
||||
read_single_block(struct sd_card_regs *card,
|
||||
uint32_t blknr, unsigned char *buf)
|
||||
read_single_block(struct sd_card *card, uint32_t blknr, unsigned char *buf)
|
||||
{
|
||||
struct mmc_command command;
|
||||
|
||||
@@ -906,7 +902,7 @@ read_single_block(struct sd_card_regs *card,
|
||||
command.resp_type = RESP_LEN_48;
|
||||
command.data_type = DATA_READ;
|
||||
command.data = buf;
|
||||
command.data_len = 512;
|
||||
command.data_len = card->blk_size;
|
||||
|
||||
if (mmc_send_cmd(&command)) {
|
||||
log_warn(&log, "Error sending command\n");
|
||||
@@ -917,7 +913,7 @@ read_single_block(struct sd_card_regs *card,
|
||||
}
|
||||
|
||||
int
|
||||
write_single_block(struct sd_card_regs *card,
|
||||
write_single_block(struct sd_card *card,
|
||||
uint32_t blknr, unsigned char *buf)
|
||||
{
|
||||
struct mmc_command command;
|
||||
@@ -927,7 +923,7 @@ write_single_block(struct sd_card_regs *card,
|
||||
command.resp_type = RESP_LEN_48;
|
||||
command.data_type = DATA_WRITE;
|
||||
command.data = buf;
|
||||
command.data_len = 512;
|
||||
command.data_len = card->blk_size;
|
||||
|
||||
/* write single block */
|
||||
if (mmc_send_cmd(&command)) {
|
||||
@@ -945,14 +941,6 @@ mmchs_host_init(struct mmc_host *host)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
mmchs_set_log_level(int level)
|
||||
{
|
||||
if (level >= 0 && level <= 4) {
|
||||
log.log_level = level;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
mmchs_host_set_instance(struct mmc_host *host, int instance)
|
||||
{
|
||||
@@ -980,9 +968,11 @@ mmchs_card_detect(struct sd_slot *slot)
|
||||
struct sd_card *
|
||||
mmchs_card_initialize(struct sd_slot *slot)
|
||||
{
|
||||
int blksize;
|
||||
struct sd_card *card;
|
||||
|
||||
mmchs_init(1);
|
||||
|
||||
struct sd_card *card;
|
||||
card = &slot->card;
|
||||
memset(card, 0, sizeof(struct sd_card));
|
||||
card->slot = slot;
|
||||
@@ -1028,7 +1018,6 @@ mmchs_card_initialize(struct sd_slot *slot)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int blksize;
|
||||
switch (SD_CSD_READ_BL_LEN(slot->card.regs.csd)) {
|
||||
case 0x09:
|
||||
blksize = 512;
|
||||
@@ -1044,6 +1033,7 @@ mmchs_card_initialize(struct sd_slot *slot)
|
||||
return NULL;
|
||||
}
|
||||
slot->card.blk_size = blksize;
|
||||
|
||||
int version;
|
||||
switch (SD_CSD_CSDVER(slot->card.regs.csd)) {
|
||||
case 0:
|
||||
@@ -1070,7 +1060,11 @@ mmchs_card_initialize(struct sd_slot *slot)
|
||||
slot->card.part[0].dv_size =
|
||||
(unsigned long long) SD_CSD_V2_CAPACITY(slot->card.regs.csd) * blksize;
|
||||
|
||||
log_info(&log, "dv_size: %d, blksize: %d\n", slot->card.part[0].dv_size, slot->card.blk_size);
|
||||
log_debug(&log, "CARD: blk_size %ld blk_count %ld\n", slot->card.blk_size, slot->card.blk_count);
|
||||
log_debug(&log, "part0: dv_base %lld dv_size %lld\n", slot->card.part[0].dv_base, slot->card.part[0].dv_size);
|
||||
log_debug(&log, "part1: dv_base %lld dv_size %lld\n", slot->card.part[1].dv_base, slot->card.part[1].dv_size);
|
||||
log_debug(&log, "part2: dv_base %lld dv_size %lld\n", slot->card.part[2].dv_base, slot->card.part[2].dv_size);
|
||||
log_debug(&log, "part3: dv_base %lld dv_size %lld\n", slot->card.part[3].dv_base, slot->card.part[3].dv_size);
|
||||
return &slot->card;
|
||||
}
|
||||
|
||||
@@ -1079,11 +1073,9 @@ static int
|
||||
mmchs_host_read(struct sd_card *card,
|
||||
uint32_t blknr, uint32_t count, unsigned char *buf)
|
||||
{
|
||||
uint32_t i;
|
||||
i = count;
|
||||
for (i = 0; i < count; i++) {
|
||||
log_info(&log, "read %d block\n", i);
|
||||
read_single_block(&card->regs, blknr + i,
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
log_info(&log, "read %d block nr %p blk_size %d count %d\n", blknr + i, buf + (i * card->blk_size), card->blk_size, count);
|
||||
read_single_block(card, blknr + i,
|
||||
buf + (i * card->blk_size));
|
||||
}
|
||||
return OK;
|
||||
@@ -1098,8 +1090,8 @@ mmchs_host_write(struct sd_card *card,
|
||||
|
||||
i = count;
|
||||
for (i = 0; i < count; i++) {
|
||||
log_info(&log, "write %d block\n", i);
|
||||
write_single_block(&card->regs, blknr + i,
|
||||
log_info(&log, "write %d block nr\n", blknr + i);
|
||||
write_single_block(card, blknr + i,
|
||||
buf + (i * card->blk_size));
|
||||
}
|
||||
|
||||
@@ -1136,7 +1128,6 @@ host_initialize_host_structure_mmchs(struct mmc_host *host)
|
||||
assert(mmchs);
|
||||
host->host_set_instance = mmchs_host_set_instance;
|
||||
host->host_init = mmchs_host_init;
|
||||
host->set_log_level = mmchs_set_log_level;
|
||||
host->host_reset = mmchs_host_reset;
|
||||
host->card_detect = mmchs_card_detect;
|
||||
host->card_initialize = mmchs_card_initialize;
|
||||
@@ -1151,4 +1142,7 @@ host_initialize_host_structure_mmchs(struct mmc_host *host)
|
||||
host->slot[i].host = host;
|
||||
host->slot[i].card.slot = &host->slot[i];
|
||||
}
|
||||
|
||||
/* Customize name for logs */
|
||||
log.name = "mmc_rpi";
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
.include <bsd.own.mk>
|
||||
|
||||
PROGS= omap_mmc omap_emmc
|
||||
MAN.omap_emmc=
|
||||
MAN.omap_mmc=
|
||||
BINDIR= /service/
|
||||
|
||||
SRCS.omap_emmc+= emmc.c mmcblk.c
|
||||
|
||||
.include "../Makefile.inc"
|
||||
|
||||
SRCS.omap_mmc= ${MMC_SRCS}
|
||||
SRCS.omap_mmc += mmchost_mmchs.c
|
||||
|
||||
DPADD+= ${LIBBLOCKDRIVER} ${LIBSYS}
|
||||
LDADD+= -lblockdriver -lsys
|
||||
CLEANFILES+=.depend mmcblk.d
|
||||
|
||||
#
|
||||
# This is a system driver.
|
||||
CPPFLAGS+= -D_SYSTEM=1
|
||||
|
||||
.include <minix.service.mk>
|
||||
@@ -1,23 +0,0 @@
|
||||
.include <bsd.own.mk>
|
||||
|
||||
PROGS= rpi_mmc rpi_emmc
|
||||
MAN.rpi_emmc=
|
||||
MAN.rpi_mmc=
|
||||
BINDIR= /service/
|
||||
|
||||
SRCS.rpi_emmc+= emmc.c mmcblk.c
|
||||
|
||||
.include "../Makefile.inc"
|
||||
|
||||
SRCS.rpi_mmc= ${MMC_SRCS}
|
||||
SRCS.rpi_mmc += mmchost_mmchs.c
|
||||
|
||||
DPADD+= ${LIBBLOCKDRIVER} ${LIBSYS}
|
||||
LDADD+= -lblockdriver -lsys
|
||||
CLEANFILES+=.depend mmcblk.d
|
||||
|
||||
#
|
||||
# This is a system driver.
|
||||
CPPFLAGS+= -D_SYSTEM=1
|
||||
|
||||
.include <minix.service.mk>
|
||||
@@ -94,10 +94,10 @@ dir.acpi:= minix/drivers/power/acpi
|
||||
.endif # ${MACHINE_ARCH} == "i386"
|
||||
|
||||
.if ${MACHINE_ARCH} == "earm"
|
||||
PROGRAMS+= rpi_mmc
|
||||
dir.rpi_mmc:= minix/drivers/storage/mmc/rpi
|
||||
PROGRAMS+= omap_mmc
|
||||
dir.omap_mmc:= minix/drivers/storage/mmc/omap
|
||||
dir.omap_mmc:= minix/drivers/storage/mmc
|
||||
PROGRAMS+= rpi_mmc
|
||||
dir.rpi_mmc:= minix/drivers/storage/mmc
|
||||
PROGRAMS+= mailbox
|
||||
dir.mailbox:= minix/drivers/system/mailbox
|
||||
.endif # ${MACHINE_ARCH} == "earm"
|
||||
|
||||
@@ -45,15 +45,9 @@ then if [ -e $ACPI -a -n "`sysenv acpi`" ]
|
||||
/bin/umount /proc >/dev/null
|
||||
fi
|
||||
|
||||
# XXX: We don't have anything better to do on Raspberry Pi yet
|
||||
if [ "$(/bin/sysenv board_name)" = "RPI_2_B" ] || [ "$(/bin/sysenv board_name)" = "RPI_3_B" ]
|
||||
then
|
||||
exec /bin/sh < /dev/console
|
||||
fi
|
||||
|
||||
if [ X`/bin/sysenv arch` = Xearm ]
|
||||
then echo Starting the mmc driver
|
||||
/bin/service -c up /service/rpi_mmc -dev /dev/c0d0
|
||||
/bin/service -c up /service/rpi_mmc -args "log_level=5" -dev /dev/c0d0
|
||||
fi
|
||||
|
||||
/bin/service up /service/procfs || echo "WARNING: couldn't start procfs"
|
||||
@@ -110,6 +104,12 @@ fi
|
||||
|
||||
/bin/mount -e -n -t procfs none /proc || echo "WARNING: couldn't mount procfs"
|
||||
|
||||
# XXX: We don't have anything better to do on Raspberry Pi yet
|
||||
if [ "$(/bin/sysenv board_name)" = "RPI_2_B" ] || [ "$(/bin/sysenv board_name)" = "RPI_3_B" ]
|
||||
then
|
||||
exec /bin/sh < /dev/console
|
||||
fi
|
||||
|
||||
if ! sysenv bootramdisk >/dev/null
|
||||
then
|
||||
exec /bin/sh /etc/rc `sysenv bootopts` "$@"
|
||||
|
||||
Reference in New Issue
Block a user