[MAJOR] The SDCard RPI driver first commit

The new driver for RPI added. There are two variants mmc and emmc
for each platform. It's not good solution, because each two implementations
differ by the registers set, the base address and some functionality.
This driver doesn't work. It'll be fixed in the future.
This commit is contained in:
Korobov Nikita
2017-06-27 01:56:57 +03:00
parent 6192a53b2d
commit 03eaf9dac8
19 changed files with 2604 additions and 1589 deletions

View File

@@ -16,12 +16,14 @@
./etc/system.conf.d/usbd minix-base
./service/bmp085 minix-base
./service/cat24c256 minix-base
./service/emmc minix-base
./service/omap_emmc minix-base
./service/rpi_emmc minix-base
./service/fb minix-base
./service/gpio minix-base
./service/i2c minix-base
./service/lan8710a minix-base
./service/mmc minix-base
./service/omap_mmc minix-base
./service/rpi_mmc minix-base
./service/random minix-base
./service/sht21 minix-base
./service/tda19988 minix-base

View File

@@ -430,7 +430,7 @@ service devman
;
};
service mmc
service omap_mmc
{
system
PRIVCTL # 4
@@ -444,6 +444,19 @@ service mmc
priority 4; # priority queue 4
};
service rpi_mmc
{
system
PRIVCTL # 4
IRQCTL # 19
;
# Interrupts allowed
irq
24
; # IRQs allowed
priority 4; # priority queue 4
};
service fb
{
system
@@ -526,7 +539,19 @@ service edfictl
ipc ALL;
};
service emmc
service rpi_emmc
{
system
PRIVCTL
IRQCTL
PADCONF
;
irq
28 # MMCSD1INT
;
};
service omap_emmc
{
system
PRIVCTL

View File

@@ -1,18 +1,4 @@
# Makefile for the mmc driver.
PROGS= mmc emmc
MAN.mmc=
MAN.emmc=
.include <bsd.own.mk>
SUBDIR+= rpi omap
SRCS.mmc= mmcblk.c mmchost_dummy.c sdhcreg.h sdmmcreg.h
SRCS.mmc += mmchost_mmchs.c
SRCS.emmc= emmc.c mmcblk.c
DPADD+= ${LIBBLOCKDRIVER} ${LIBSYS}
LDADD+= -lblockdriver -lsys
CLEANFILES+=.depend mmcblk.d
#
# This is a system driver.
CPPFLAGS+= -D_SYSTEM=1
.include <minix.service.mk>
.include <bsd.subdir.mk>

View File

@@ -1,663 +0,0 @@
/*
* Block driver for Multi Media Cards (MMC).
*/
/* kernel headers */
#include <minix/syslib.h>
#include <minix/driver.h>
#include <minix/blockdriver.h>
#include <minix/drvlib.h>
#include <minix/log.h>
#include <minix/minlib.h>
/* system headers */
#include <sys/ioc_disk.h> /* disk IOCTL's */
/* usr headers */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <signal.h>
/* local headers */
#include "mmchost.h"
/* used for logging */
static struct log log = {
.name = "mmc_block",
.log_level = LEVEL_INFO,
.log_func = default_log
};
/* holding the current host controller */
static struct mmc_host host;
#define NR_SUBDEVS (MAX_DRIVES * SUB_PER_DRIVE)
/* When passing data over a grant one needs to pass
* a buffer to sys_safecopy copybuff is used for that*/
#define COPYBUFF_SIZE 0x1000 /* 4k buff */
static unsigned char copybuff[COPYBUFF_SIZE];
static struct sd_slot *get_slot(devminor_t minor);
/* Prototypes for the block device */
static int block_open(devminor_t minor, int access);
static int block_close(devminor_t minor);
static int block_transfer(devminor_t minor,
int do_write,
u64_t position,
endpoint_t endpt, iovec_t * iov, unsigned int nr_req, int flags);
static int block_ioctl(devminor_t minor, unsigned long request,
endpoint_t endpt, cp_grant_id_t grant, endpoint_t user_endpt);
static struct device *block_part(devminor_t minor);
/* System even handling */
static void sef_local_startup();
static int block_system_event_cb(int type, sef_init_info_t * info);
static void block_signal_handler_cb(int signo);
void
bdr_alarm(clock_t stamp)
{
log_debug(&log, "alarm %d\n", stamp);
}
static int apply_env();
static void hw_intr(unsigned int irqs);
/* set the global logging level */
static void set_log_level(int level);
/* Entry points for the BLOCK driver. */
static struct blockdriver mmc_driver = {
.bdr_type = BLOCKDRIVER_TYPE_DISK,/* handle partition requests */
.bdr_open = block_open, /* device open */
.bdr_close = block_close, /* on a close */
.bdr_transfer = block_transfer, /* does the I/O */
.bdr_ioctl = block_ioctl, /* ioctls */
.bdr_part = block_part, /* get partition information */
.bdr_intr = hw_intr, /* left over interrupts */
.bdr_alarm = bdr_alarm /* no alarm processing */
};
static void
hw_intr(unsigned int irqs)
{
log_debug(&log, "Hardware inter left over\n");
host.hw_intr(irqs);
}
static int
apply_env()
{
long v;
/* apply the env setting passed to this driver parameters accepted
* log_level=[0-4] (NONE,WARN,INFO,DEBUG,TRACE) instance=[0-3]
* instance/bus number to use for this driver Passing these arguments
* is done when starting the driver using the service command in the
* following way service up /service/mmc -args "log_level=2 instance=1
* driver=dummy" -dev /dev/c2d0 */
char driver[16];
memset(driver, '\0', 16);
(void) env_get_param("driver", driver, 16);
if (strlen(driver) == 0
|| strncmp(driver, "mmchs", strlen("mmchs") + 1) == 0) {
/* early init of host mmc host controller. This code should
* depend on knowing the hardware that is running bellow. */
#ifdef __arm__
host_initialize_host_structure_mmchs(&host);
#endif
} else if (strncmp(driver, "dummy", strlen("dummy") + 1) == 0) {
host_initialize_host_structure_dummy(&host);
} else {
log_warn(&log, "Unknown driver %s\n", driver);
}
/* Initialize the verbosity level. */
v = 0;
if (env_parse("log_level", "d", 0, &v, LEVEL_NONE,
LEVEL_TRACE) == EP_SET) {
set_log_level(v);
}
/* Find out which driver instance we are. */
v = 0;
env_parse("instance", "d", 0, &v, 0, 3);
if (host.host_set_instance(&host, v)) {
log_warn(&log, "Failed to set mmc instance to %d\n", v);
return -1; /* NOT OK */
}
return OK;
}
;
/*===========================================================================*
* block_open *
*===========================================================================*/
static int
block_open(devminor_t minor, int access)
{
struct sd_slot *slot;
slot = get_slot(minor);
int i, j;
int part_count, sub_part_count;
i = j = part_count = sub_part_count = 0;
if (!slot) {
log_debug(&log, "Not handling open on non existing slot\n");
return EIO;
}
assert(slot->host != NULL);
if (!slot->host->card_detect(slot)) {
log_debug(&log, "No card inserted in the SD slot\n");
return EIO;
}
/* If we are already open just increase the open count and return */
if (slot->card.state == SD_MODE_DATA_TRANSFER_MODE) {
assert(slot->card.open_ct >= 0);
slot->card.open_ct++;
log_trace(&log, "increased open count to %d\n",
slot->card.open_ct);
return OK;
}
/* We did not have an sd-card inserted so we are going to probe for it
*/
log_debug(&log, "First open on (%d)\n", minor);
if (!host.card_initialize(slot)) {
// * TODO: set card state to INVALID until removed? */
return EIO;
}
partition(&mmc_driver, 0 /* first card on bus */ , P_PRIMARY,
0 /* atapi device?? */ );
log_trace(&log, "descr \toffset(bytes) size(bytes)\n", minor);
log_trace(&log, "disk %d\t0x%016llx 0x%016llx\n", i,
slot->card.part[0].dv_base, slot->card.part[0].dv_size);
for (i = 1; i < 5; i++) {
if (slot->card.part[i].dv_size == 0)
continue;
part_count++;
log_trace(&log, "part %d\t0x%016llx 0x%016llx\n", i,
slot->card.part[i].dv_base, slot->card.part[i].dv_size);
for (j = 0; j < 4; j++) {
if (slot->card.subpart[(i - 1) * 4 + j].dv_size == 0)
continue;
sub_part_count++;
log_trace(&log,
" sub %d/%d\t0x%016llx 0x%016llx\n", i, j,
slot->card.subpart[(i - 1) * 4 + j].dv_base,
slot->card.subpart[(i - 1) * 4 + j].dv_size);
}
}
log_debug(&log, "Found %d partitions and %d sub partitions\n",
part_count, sub_part_count);
slot->card.open_ct++;
assert(slot->card.open_ct == 1);
return OK;
}
/*===========================================================================*
* block_close *
*===========================================================================*/
static int
block_close(devminor_t minor)
{
struct sd_slot *slot;
slot = get_slot(minor);
if (!slot) {
log_debug(&log, "Not handling open on non existing slot\n");
return EIO;
}
/* if we arrived here we expect a card to be present, we will need do
* deal with removal later */
assert(slot->host != NULL);
assert(slot->card.open_ct >= 1);
/* If this is not the last open count simply decrease the counter and
* return */
if (slot->card.open_ct > 1) {
slot->card.open_ct--;
log_trace(&log, "decreased open count to %d\n",
slot->card.open_ct);
return OK;
}
assert(slot->card.open_ct == 1);
log_debug(&log, "freeing the block device as it is no longer used\n");
/* release the card as check the open_ct should be 0 */
slot->host->card_release(&slot->card);
assert(slot->card.open_ct == 0);
return OK;
}
static int
copyto(endpoint_t dst_e,
cp_grant_id_t gr_id, vir_bytes offset, vir_bytes address, size_t bytes)
{
/* Helper function that used memcpy to copy data when the endpoint ==
* SELF */
if (dst_e == SELF) {
memcpy((char *) gr_id + offset, (char *) address, bytes);
return OK;
} else {
/* Read io_size bytes from our data at the correct * offset
* and write it to the output buffer at 0 */
return sys_safecopyto(dst_e, gr_id, offset, address, bytes);
}
}
static int
copyfrom(endpoint_t src_e,
cp_grant_id_t gr_id, vir_bytes offset, vir_bytes address, size_t bytes)
{
/* Helper function that used memcpy to copy data when the endpoint ==
* SELF */
if (src_e == SELF) {
memcpy((char *) address, (char *) gr_id + offset, bytes);
return OK;
} else {
return sys_safecopyfrom(src_e, gr_id, offset, address, bytes);
}
}
/*===========================================================================*
* block_transfer *
*===========================================================================*/
static int
block_transfer(
devminor_t minor, /* minor device number */
int do_write, /* read or write? */
u64_t position, /* offset on device to read or write */
endpoint_t endpt, /* process doing the request */
iovec_t * iov, /* pointer to read or write request vector */
unsigned int nr_req, /* length of request vector */
int flags /* transfer flags */
)
{
unsigned long counter;
iovec_t *ciov; /* Current IO Vector */
struct device *dev; /* The device used */
struct sd_slot *slot; /* The sd slot the requests is pointed to */
vir_bytes io_size; /* Size to read/write to/from the iov */
vir_bytes io_offset; /* Size to read/write to/from the iov */
vir_bytes bytes_written;
int r, blk_size, i;
/* Get the current "device" geometry */
dev = block_part(minor);
if (dev == NULL) {
log_warn(&log,
"Transfer requested on unknown device minor(%d)\n", minor);
/* Unknown device */
return ENXIO;
}
log_trace(&log, "I/O on minor(%d) %s at 0x%016llx\n", minor,
(do_write) ? "Write" : "Read", position);
slot = get_slot(minor);
assert(slot);
if (slot->card.blk_size == 0) {
log_warn(&log, "Request on a card with block size of 0\n");
return EINVAL;
}
if (slot->card.blk_size > COPYBUFF_SIZE) {
log_warn(&log,
"Card block size (%d) exceeds internal buffer size %d\n",
slot->card.blk_size, COPYBUFF_SIZE);
return EINVAL;
}
/* It is fully up to the driver to decide on restrictions for the
* parameters of transfers, in those cases we return EINVAL */
if (position % slot->card.blk_size != 0) {
/* Starting at a block boundary */
log_warn(&log,
"Requests must start at a block boundary"
"(start,block size)=(%016llx,%08x)\n", position,
slot->card.blk_size);
return EINVAL;
}
blk_size = slot->card.blk_size;
bytes_written = 0;
/* Are we trying to start reading past the end */
if (position >= dev->dv_size) {
log_warn(&log, "start reading past drive size\n");
return 0;
};
ciov = iov;
/* do some more validation */
for (counter = 0; counter < nr_req; counter++) {
assert(ciov != NULL);
if (ciov->iov_size % blk_size != 0) {
/* transfer a multiple of blk_size */
log_warn(&log,
"Requests must start at a block boundary "
"(start,block size)=(%016llx,%08x)\n", position,
slot->card.blk_size);
return EINVAL;
}
if (ciov->iov_size <= 0) {
log_warn(&log,
"Invalid iov size for iov %d of %d size\n",
counter, nr_req, ciov->iov_size);
return EINVAL;
}
ciov++;
}
ciov = iov;
for (counter = 0; counter < nr_req; counter++) {
/* Assume we are to transfer the amount of data given in the
* input/output vector but ensure we are not doing i/o past
* our own boundaries */
io_size = ciov->iov_size;
io_offset = position + bytes_written;
/* Check we are not reading/writing past the end */
if (position + bytes_written + io_size > dev->dv_size) {
io_size = dev->dv_size - (position + bytes_written);
};
log_trace(&log,
"I/O %s request(%d/%d) iov(grant,size,iosize,"
"offset)=(%d,%d,%d,%d)\n",
(do_write) ? "write" : "read", counter + 1, nr_req,
ciov->iov_addr, ciov->iov_size, io_size, io_offset);
/* transfer max one block at the time */
for (i = 0; i < io_size / blk_size; i++) {
if (do_write) {
/* Read io_size bytes from i/o vector starting
* at 0 and write it to out buffer at the
* correct offset */
r = copyfrom(endpt, ciov->iov_addr,
i * blk_size, (vir_bytes) copybuff,
blk_size);
if (r != OK) {
log_warn(&log,
"I/O write error: %s iov(base,size)=(%d,%d)"
" at offset=%d\n",
strerror(_SIGN r), ciov->iov_addr,
ciov->iov_size, io_offset);
return EINVAL;
}
/* write a single block */
slot->host->write(&slot->card,
(dev->dv_base / blk_size) +
(io_offset / blk_size) + i, 1, copybuff);
bytes_written += blk_size;
} else {
/* read a single block info copybuff */
slot->host->read(&slot->card,
(dev->dv_base / blk_size) +
(io_offset / blk_size) + i, 1, copybuff);
/* Read io_size bytes from our data at the
* correct offset and write it to the output
* buffer at 0 */
r = copyto(endpt, ciov->iov_addr, i * blk_size,
(vir_bytes) copybuff, blk_size);
if (r != OK) {
log_warn(&log,
"I/O read error: %s iov(base,size)=(%d,%d)"
" at offset=%d\n",
strerror(_SIGN r), ciov->iov_addr,
ciov->iov_size, io_offset);
return EINVAL;
}
bytes_written += blk_size;
}
}
ciov++;
}
return bytes_written;
}
/*===========================================================================*
* block_ioctl *
*===========================================================================*/
static int
block_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
cp_grant_id_t grant, endpoint_t UNUSED(user_endpt))
{
/* IOCTL handling */
struct sd_slot *slot;
log_trace(&log,
"enter (minor,request,endpoint,grant)=(%d,%lu,%d)\n", minor,
request, endpt, grant);
slot = get_slot(minor);
if (!slot) {
log_warn(&log,
"Doing ioctl on non existing block device(%d)\n", minor);
return EINVAL;
}
switch (request) {
case DIOCOPENCT:
// TODO: add a check for card validity */
log_trace(&log, "returning open count %d\n",
slot->card.open_ct);
/* return the current open count */
return sys_safecopyto(endpt, grant, 0,
(vir_bytes) & slot->card.open_ct,
sizeof(slot->card.open_ct));
case DIOCFLUSH:
/* No need to flush but some devices like movinands require
* 500 ms inactivity */
return OK;
}
return ENOTTY;
}
/*===========================================================================*
* block_part *
*===========================================================================*/
static struct device *
block_part(devminor_t minor)
{
/*
* Reuse the existing MINIX major/minor partitioning scheme.
* - 8 drives
* - 5 devices per drive allowing direct access to the disk and up to 4
* partitions (IBM style partitioning without extended partitions)
* - 4 Minix style sub partitions per partitions
*/
struct device *dev;
struct sd_slot *slot;
dev = NULL;
slot = get_slot(minor);
if (!slot) {
log_warn(&log,
"Device information requested for non existing partition "
"minor(%d)\n", minor);
return NULL;
}
if (!slot->host->card_detect(slot)) {
log_warn(&log,
"Device information requested from empty slot(%d)\n",
minor);
return NULL;
}
if (minor < 5) {
/* we are talking about the first disk */
dev = &slot->card.part[minor];
log_trace(&log,
"returning partition(%d) (base,size)=(0x%016llx,0x%016llx)\n",
minor, dev->dv_base, dev->dv_size);
} else if (minor >= 128 && minor < 128 + 16) {
/* sub partitions of the first disk we don't care about the
* rest */
dev = &slot->card.subpart[minor - 128];
log_trace(&log,
"returning sub partition(%d) (base,size)=(0x%016llx,0x%016llx)\n",
minor - 128, dev->dv_base, dev->dv_size);
} else {
log_warn(&log,
"Device information requested for non existing "
"partition minor(%d)\n", minor);
}
return dev;
}
/*===========================================================================*
* sef_local_startup *
*===========================================================================*/
static void
sef_local_startup()
{
log_info(&log, "Initializing the MMC block device\n");
if (apply_env()) {
log_warn(&log, "Failed while applying environment settings\n");
exit(EXIT_FAILURE);
}
if (host.host_init(&host)) {
log_warn(&log, "Failed to initialize the host controller\n");
exit(EXIT_FAILURE);
}
/*
* Register callbacks for fresh start, live update and restart.
* Use the same function for all event types
*/
sef_setcb_init_fresh(block_system_event_cb);
/* Register a signal handler */
sef_setcb_signal_handler(block_signal_handler_cb);
/* SEF startup */
sef_startup();
}
/*===========================================================================*
* block_system_event_cb *
*===========================================================================*/
static int
block_system_event_cb(int type, sef_init_info_t * info)
{
/*
* Callbacks for the System event framework as registered in
* sef_local_startup */
switch (type) {
case SEF_INIT_FRESH:
log_info(&log, "System event framework fresh start\n");
break;
case SEF_INIT_LU:
/* Restore the state. post update */
log_info(&log, "System event framework live update\n");
break;
case SEF_INIT_RESTART:
log_info(&log, "System event framework post restart\n");
break;
}
blockdriver_announce(type);
return OK;
}
/*===========================================================================*
* block_signal_handler_cb *
*===========================================================================*/
static void
block_signal_handler_cb(int signo)
{
struct sd_slot *slot;
log_debug(&log, "System event framework signal handler sig(%d)\n",
signo);
/* Only check for termination signal, ignore anything else. */
if (signo != SIGTERM)
return;
/* we only have a single slot and need an open count idealy we should
* iterate over the card to determine the open count */
slot = get_slot(0);
assert(slot);
if (slot->card.open_ct > 0) {
log_debug(&log, "Not responding to SIGTERM (open count=%d)\n",
slot->card.open_ct);
return;
}
log_info(&log, "MMC driver exit");
exit(0);
}
#define IS_MINIX_SUB_PARTITION_MINOR(minor) (minor >= MINOR_d0p0s0 )
static struct sd_slot *
get_slot(devminor_t minor)
{
/*
* Get an sd_slot based on the minor number.
*
* This driver only supports a single card at at time. Also as
* we are following the major/minor scheme of other driver we
* must return a slot for all minors on disk 0 these are 0-5
* for the disk and 4 main partitions and
* number 128 till 144 for sub partitions.
*/
/* If this is a minor for the first disk (e.g. minor 0 till 5) */
if (minor >= 0 && minor / DEV_PER_DRIVE == 0) {
/* we are talking about the first disk and that is all we
* support */
return &host.slot[0];
} else if (IS_MINIX_SUB_PARTITION_MINOR(minor)
&& (((minor - MINOR_d0p0s0) / SUB_PER_DRIVE) == 0)) {
/* a minor from the first disk */
return &host.slot[0];
} else {
log_trace(&log,
"Device information requested for non existing partition "
"minor(%d)\n", minor);
return NULL;
}
}
static void
set_log_level(int level)
{
if (level < 0 || level >= 4) {
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
main(int argc, char **argv)
{
/* Set and apply the environment */
env_setargs(argc, argv);
sef_local_startup();
blockdriver_task(&mmc_driver);
return EXIT_SUCCESS;
}

View File

@@ -1,156 +0,0 @@
#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 */
/**
* We can have multiple MMC host controller present on the hardware. The MINIX
* approach to handle this is to run a driver for each instance. Every driver
* will therefore be stated with an "instance" id and the rest of the code here
* will assume a single host controller to be present.
*
* The SD specification allows multiple cards to be attached to a single host
* controller using the same lines. I recommend reading SD Specifications Part 1
* Physical layer Simplified Specification chapter 3 about SD Memory Card system
* concepts if you want to get a better understanding of this.
*
* In practice an MMC host will usually have a single slot attached to it and that
* Slot may or may not contain a card. On sudden card removal we might want to
* keep track of the last inserted card and we might therefore at later stage
* add an additional "last_card" attribute to the card.
*
* The following diagram shows the structure that will be used to modulate the
* hardware written in umlwiki syntax.
*
* [/host/
* +instance:int] 1 --- 0..4 [ /slot/
* +card_detect:func ] 1 --- 0..1 [ /card/ ]
* `
*/
#define MAX_SD_SLOTS 4
struct mmc_host;
//TODO Add more modes like INACTIVE STATE and such
#define SD_MODE_UNINITIALIZED 0
#define SD_MODE_CARD_IDENTIFICATION 1
#define SD_MODE_DATA_TRANSFER_MODE 2
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 */
};
#define RESP_LEN_48_CHK_BUSY (3<<0)
#define RESP_LEN_48 (2<<0)
#define RESP_LEN_136 (1<<0)
#define RESP_NO_RESPONSE (0<<0)
#define DATA_NONE (0)
#define DATA_READ (1)
#define DATA_WRITE (2)
/* struct representing an mmc command */
struct mmc_command
{
uint32_t cmd;
uint32_t args;
uint32_t resp_type;
uint32_t data_type;
uint32_t resp[4];
unsigned char *data;
uint32_t data_len;
};
/* structure representing an SD card */
struct sd_card
{
/* pointer back to the SD slot for convenience */
struct sd_slot *slot;
struct sd_card_regs regs;
/* some helpers (data comming from the csd) */
uint32_t blk_size;
uint32_t blk_count;
/* drive state: deaf, initialized, dead */
unsigned state;
/* MINIX/block driver related things */
int open_ct; /* in-use count */
/* 1 disks + 4 partitions and 16 possible sub partitions */
struct device part[MINOR_PER_DISK + PARTITONS_PER_DISK];
struct device subpart[PARTITONS_PER_DISK * SUBPARTITION_PER_PARTITION];
};
/* structure representing an SD slot */
struct sd_slot
{
/* pointer back to the host for convenience */
struct mmc_host *host;
unsigned state;
struct sd_card card;
};
/* structure for the host controller */
struct mmc_host
{
/* MMC host configuration */
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) */
int (*card_detect) (struct sd_slot * slot);
/* Perform card detection e.g. card type */
struct sd_card *(*card_initialize) (struct sd_slot * slot);
/* Release the card */
int (*card_release) (struct sd_card * card);
/* Additional hardware interrupts */
void (*hw_intr) (unsigned int irqs);
/* read count blocks into existing buf */
int (*read) (struct sd_card * card,
uint32_t blknr, uint32_t count, unsigned char *buf);
/* write count blocks */
int (*write) (struct sd_card * card,
uint32_t blknr, uint32_t count, unsigned char *buf);
/* up to 4 slots with 4 SD cards */
struct sd_slot slot[MAX_SD_SLOTS];
};
#if 0
/* Command execution */
int (*send_cmd) (struct sd_card * card, struct mmc_command *);
/* struct representing an mmc command */
struct mmc_command
{
uint32_t cmd;
uint32_t args;
uint32_t resp[4];
unsigned char *data;
uint32_t data_len;
};
#endif
/* Hack done for driver registration */
void host_initialize_host_structure_mmchs(struct mmc_host *host);
void host_initialize_host_structure_dummy(struct mmc_host *host);

View File

@@ -1,170 +0,0 @@
/* kernel headers */
#include <minix/blockdriver.h>
#include <minix/minlib.h>
#include <minix/log.h>
/* usr headers */
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>
#include <unistd.h>
/* local headers */
#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
static char *dummy_data = NULL;
static struct sd_card *
init_dummy_sdcard(struct sd_slot *slot)
{
int i;
struct sd_card *card;
assert(slot != NULL);
log_info(&log, "Using a dummy card \n");
if (dummy_data == NULL) {
dummy_data = malloc(DUMMY_BLOCK_SIZE * DUMMY_SIZE_IN_BLOCKS);
if (dummy_data == NULL) {
panic
("Failed to allocate data for dummy mmc driver\n");
}
}
card = &slot->card;
memset(card, 0, sizeof(struct sd_card));
card->slot = slot;
for (i = 0; i < MINOR_PER_DISK + PARTITONS_PER_DISK; i++) {
card->part[i].dv_base = 0;
card->part[i].dv_size = 0;
}
for (i = 0; i < PARTITONS_PER_DISK * SUBPARTITION_PER_PARTITION; i++) {
card->subpart[i].dv_base = 0;
card->subpart[i].dv_size = 0;
}
card->part[0].dv_base = 0;
card->part[0].dv_size = DUMMY_BLOCK_SIZE * DUMMY_SIZE_IN_BLOCKS;
return card;
}
int
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)
{
log_info(&log, "Using instance number %d\n", instance);
if (instance != 0) {
return EIO;
}
return OK;
}
int
dummy_host_reset(struct mmc_host *host)
{
return 0;
}
int
dummy_card_detect(struct sd_slot *slot)
{
return 1;
}
struct sd_card *
dummy_card_initialize(struct sd_slot *slot)
{
slot->card.blk_size = DUMMY_BLOCK_SIZE;
slot->card.blk_count = DUMMY_SIZE_IN_BLOCKS;
slot->card.state = SD_MODE_DATA_TRANSFER_MODE;
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;
slot->card.part[0].dv_size = DUMMY_BLOCK_SIZE * DUMMY_SIZE_IN_BLOCKS;
return &slot->card;
}
int
dummy_card_release(struct sd_card *card)
{
assert(card->open_ct == 1);
card->open_ct--;
card->state = SD_MODE_UNINITIALIZED;
/* TODO:Set card state */
return OK;
}
/* read count blocks into existing buf */
int
dummy_host_read(struct sd_card *card,
uint32_t blknr, uint32_t count, unsigned char *buf)
{
memcpy(buf, &dummy_data[blknr * DUMMY_BLOCK_SIZE],
count * DUMMY_BLOCK_SIZE);
return OK;
}
/* write count blocks */
int
dummy_host_write(struct sd_card *card,
uint32_t blknr, uint32_t count, unsigned char *buf)
{
memcpy(&dummy_data[blknr * DUMMY_BLOCK_SIZE], buf,
count * DUMMY_BLOCK_SIZE);
return OK;
}
void
host_initialize_host_structure_dummy(struct mmc_host *host)
{
/* Initialize the basic data structures host slots and cards */
int i;
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;
host->card_release = dummy_card_release;
host->read = dummy_host_read;
host->write = dummy_host_write;
/* initialize data structures */
for (i = 0; i < sizeof(host->slot) / sizeof(host->slot[0]); i++) {
// @TODO set initial card and slot state
host->slot[i].host = host;
host->slot[i].card.slot = &host->slot[i];
}
init_dummy_sdcard(&host->slot[0]);
}

View File

@@ -0,0 +1,23 @@
.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>

View File

@@ -8,8 +8,8 @@
#include <sys/mman.h>
#include "omap_mmc.h"
#include "mmchost.h"
#include "sdmmcreg.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 */

View File

@@ -21,12 +21,11 @@
#include <unistd.h>
/* local headers */
#include "mmchost.h"
#include "../mmchost.h"
/* header imported from netbsd */
#include "sdmmcreg.h"
#include "sdmmcreg.h"
#include "sdhcreg.h"
#include "../sdmmcreg.h"
#include "../sdhcreg.h"
/* omap /hardware related */
#include "omap_mmc.h"

View File

@@ -0,0 +1,23 @@
.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>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,282 @@
#ifndef __SD_H__
#define __SD_H__
#define RW
#define R
typedef struct {
RW vir_bytes blkscnt;
RW vir_bytes arg1;
RW vir_bytes cmdtm;
R vir_bytes resp0;
R vir_bytes resp1;
R vir_bytes resp2;
R vir_bytes resp3;
RW vir_bytes data;
R vir_bytes status;
RW vir_bytes control0;
RW vir_bytes control1;
RW vir_bytes irpt;
RW vir_bytes irpt_mask;
RW vir_bytes irpt_en;
RW vir_bytes control2;
RW vir_bytes slotisr_var;
} rpi_mmchs_registers;
rpi_mmchs_registers regs_v0 = {
.blkscnt = 0x4,
.arg1 = 0x8,
.cmdtm = 0xc,
.resp0 = 0x10,
.resp1 = 0x14,
.resp2 = 0x18,
.resp3 = 0x1c,
.data = 0x20,
.status = 0x24,
.control0 = 0x28,
.control1 = 0x2c,
.irpt = 0x30,
.irpt_mask = 0x34,
.irpt_en = 0x38,
.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 */
#define MMCHS_SD_SYSCONFIG_SOFTRESET (0x1 << 1) /* Software reset bit writing */
#define MMCHS_SD_SYSCONFIG_ENAWAKEUP (0x1 << 2) /* Wake-up feature control */
#define MMCHS_SD_SYSCONFIG_ENAWAKEUP_DIS (0x0 << 2) /* Disable wake-up capability */
#define MMCHS_SD_SYSCONFIG_ENAWAKEUP_EN (0x1 << 2) /* Enable wake-up capability */
#define MMCHS_SD_SYSCONFIG_SIDLEMODE (0x3 << 3) /* Power management */
#define MMCHS_SD_SYSCONFIG_SIDLEMODE_UNCONDITIONAL (0x0 << 3) /* Go into idle mode unconditionally upon request */
#define MMCHS_SD_SYSCONFIG_SIDLEMODE_IGNORE (0x1 << 3) /* Ignore ILDE requests */
#define MMCHS_SD_SYSCONFIG_SIDLEMODE_IDLE (0x2 << 3) /* Acknowledge IDLE request switch to wake-up mode */
#define MMCHS_SD_SYSCONFIG_SIDLEMODE_SMART_IDLE (0x3 << 3) /* Smart-idle */
#define MMCHS_SD_SYSCONFIG_CLOCKACTIVITY (0x3 << 8) /* Clock activity during wake-up */
#define MMCHS_SD_SYSCONFIG_CLOCKACTIVITY_OFF (0x0 << 8) /* Interface and functional clock can be switched off */
#define MMCHS_SD_SYSCONFIG_CLOCKACTIVITY_IF (0x1 << 8) /* Only Interface clock (functional can be switched off*/
#define MMCHS_SD_SYSCONFIG_CLOCKACTIVITY_FUNC (0x2 << 8) /* Only Functional clock (interface clock can be switched off) */
#define MMCHS_SD_SYSCONFIG_CLOCKACTIVITY_BOOTH (0x3 << 8) /* Booth the interface and functional clock are maintained */
#define MMCHS_SD_SYSCONFIG_STANDBYMODE (0x3 << 12) /* Configuration for standby */
#define MMCHS_SD_SYSCONFIG_STANDBYMODE_FORCE_STANDBY (0x0 << 12) /* Force standby mode upon idle request*/
#define MMCHS_SD_SYSCONFIG_STANDBYMODE_NO_STANDBY (0x1 << 12) /* Never go into standby mode */
#define MMCHS_SD_SYSCONFIG_STANDBYMODE_WAKEUP_INTERNAL (0x2 << 12) /* Go into wake-up mode based on internal knowledge */
#define MMCHS_SD_SYSCONFIG_STANDBYMODE_WAKEUP_SMART (0x3 << 12) /* Go info wake-up mode when possible */
#define MMCHS_SD_SYSSTATUS_RESETDONE 0x01
#define MMCHS_SD_CON_DW8 (0x1 << 5) /* 8-bit mode MMC select , For SD clear this bit */
#define MMCHS_SD_CON_DW8_1BIT (0x0 << 5) /* 1 or 4 bits data width configuration(also set SD_HCTL) */
#define MMCHS_SD_CON_DW8_8BITS (0x1 << 5) /* 8 bits data width configuration */
#define MMCHS_SD_CON_INIT (0x1 << 1) /* Send initialization stream (all cards) */
#define MMCHS_SD_CON_INIT_NOINIT (0x0 << 1) /* Do nothing */
#define MMCHS_SD_CON_INIT_INIT (0x1 << 1) /* Send initialization stream */
#define MMCHS_SD_CON_OD (0x1 << 0) /* Card open drain mode (MMC cards only) */
#define MMCHS_SD_CON_OD_PP (0x0 << 0) /* No open drain (push-pull). */
#define MMCHS_SD_CON_OD_OD (0x1 << 0) /* Open drain */
#define MMCHS_SD_BLK_NBLK (0xffffu << 16) /* Block count for the current transfer */
#define MMCHS_SD_BLK_BLEN (0xfff << 0) /* Transfer block size */
#define MMCHS_SD_BLK_BLEN_NOTRANSFER (0x0 << 0) /* No transfer */
#define MMCHS_SD_CMD_INDX (0x3f << 24) /* Command index */
#define MMCHS_SD_CMD_INDX_CMD(x) (x << 24) /* MMC command index binary encoded values from 0 to 63 */
#define MMCHS_SD_ARG_MASK (0xffffffffu) /* Mask everything */
#define MMCHS_SD_ARG_CMD8_VHS (0x1 << (16 - 8)) /* Voltage between 2.7 and 3.6 v*/
#define MMCHS_SD_ARG_CMD8_CHECK_PATTERN (0xaa <<(8 - 8)) /* 10101010b pattern */
#define MMCHS_SD_CMD_TYPE (0x3 << 22) /* Command type. */
#define MMCHS_SD_CMD_TYPE_OTHER (0x0 << 22) /* Other type of commands (like go idle) */
#define MMCHS_SD_CMD_TYPE_BUS_SUSPEND (0x1 << 22) /* Upon CMD52 "Bus Suspend" operation */
#define MMCHS_SD_CMD_TYPE_FUNCTION_SELECT (0x2 << 22) /* Upon CMD52 "Function Select" operation */
#define MMCHS_SD_CMD_TYPE_IOABORT (0x3 << 22) /* Upon CMD12 and CMD21 "I/O Abort */
#define MMCHS_SD_CMD_DP (0x1 << 21) /* Data present select */
#define MMCHS_SD_CMD_DP_DATA (0x1 << 21) /* Additional data is present on the data lines */
#define MMCHS_SD_CMD_DP_NODATA (0x0 << 21) /* No additional data is present on the data lines */
#define MMCHS_SD_CMD_CICE (0x1 << 20) /* Command index response check enable */
#define MMCHS_SD_CMD_CICE_ENABLE (0x1 << 20) /* Enable index check response */
#define MMCHS_SD_CMD_CICE_DISABLE (0x0 << 20) /* Disable index check response */
#define MMCHS_SD_CMD_CCCE (0x1 << 19) /* Command CRC7 Check enable on responses*/
#define MMCHS_SD_CMD_CCCE_ENABLE (0x1 << 19) /* Enable CRC7 Check on response */
#define MMCHS_SD_CMD_CCCE_DISABLE (0x0 << 19) /* Disable CRC7 Check on response */
#define MMCHS_SD_CMD_RSP_TYPE (0x3 << 16) /* Response type */
#define MMCHS_SD_CMD_RSP_TYPE_NO_RESP (0x0 << 16) /* No response */
#define MMCHS_SD_CMD_RSP_TYPE_136B (0x1 << 16) /* Response length 136 bits */
#define MMCHS_SD_CMD_RSP_TYPE_48B (0x2 << 16) /* Response length 48 bits */
#define MMCHS_SD_CMD_RSP_TYPE_48B_BUSY (0x3 << 16) /* Response length 48 bits with busy after response */
#define MMCHS_SD_CMD_MSBS (0x1 << 5) /* Multi/Single block select */
#define MMCHS_SD_CMD_MSBS_SINGLE (0x0 << 5) /* Single block mode */
#define MMCHS_SD_CMD_MSBS_MULTI (0x0 << 5) /* Multi block mode */
#define MMCHS_SD_CMD_DDIR (0x1 << 4) /* Data transfer direction */
#define MMCHS_SD_CMD_DDIR_READ (0x1 << 4) /* Data read (card to host) */
#define MMCHS_SD_CMD_DDIR_WRITE (0x0 << 4) /* Data write (host to card) */
#define MMCHS_SD_CMD_ACEN (0x1 << 2) /* Auto CMD12 Enable */
#define MMCHS_SD_CMD_ACEN_DIS (0x0 << 2) /* Auto CMD12 Disable */
#define MMCHS_SD_CMD_ACEN_EN (0x1 << 2) /* Auto CMD12 Enable */
#define MMCHS_SD_CMD_BCE (0x1 << 1) /* Block Count Enable(for multi block transfer) */
#define MMCHS_SD_CMD_BCE_DIS (0x0 << 1) /* Disabled block count for infinite transfer*/
#define MMCHS_SD_CMD_BCE_EN (0x1 << 1) /* Enabled for multi block transfer with know amount of blocks */
#define MMCHS_SD_CMD_DE (0x1 << 0) /* DMA enable */
#define MMCHS_SD_CMD_DE_DIS (0x0 << 0) /* Disable DMA */
#define MMCHS_SD_CMD_DE_EN (0x1 << 0) /* Enable DMA */
#define MMCHS_SD_CMD_MASK ~(0x1 << 30 | 0x1 << 31 | 0x1 << 18 | 0x1 <<3) /* bits 30 , 31 and 18 are reserved */
#define MMCHS_SD_PSTATE_CI (0x1 << 16) /* Card Inserted */
#define MMCHS_SD_PSTATE_CI_INSERTED (0x1 << 16) /* Card Inserted is inserted*/
#define MMCHS_SD_PSTATE_BRE (0x1 << 11) /* Buffer read enable */
#define MMCHS_SD_PSTATE_BRE_DIS (0x0 << 11) /* Read BLEN bytes disabled*/
#define MMCHS_SD_PSTATE_BRE_EN (0x1 << 11) /* Read BLEN bytes enabled*/
#define MMCHS_SD_PSTATE_BWE (0x1 << 10) /* Buffer Write enable */
#define MMCHS_SD_PSTATE_BWE_DIS (0x0 << 10) /* There is no room left in the buffer to write BLEN bytes of data */
#define MMCHS_SD_PSTATE_BWE_EN (0x1 << 10) /* There is enough space in the buffer to write BLEN bytes of data*/
#define MMCHS_SD_PSTATE_DATI (0x1 << 1) /* Command inhibit (mmc_dat) */
#define MMCHS_SD_PSTATE_CMDI (0x1 << 0) /* Command inhibit (mmc_cmd) */
#define MMCHS_SD_HCTL_DTW (0x1 << 1) /*Data transfer width.(must be set after a successful ACMD6) */
#define MMCHS_SD_HCTL_DTW_1BIT (0x0 << 1) /*1 bit transfer with */
#define MMCHS_SD_HCTL_DTW_4BIT (0x1 << 1) /*4 bit transfer with */
#define MMCHS_SD_HCTL_SDBP (0x1 << 8) /*SD bus power */
#define MMCHS_SD_HCTL_SDBP_OFF (0x0 << 8) /*SD Power off (start card detect?) */
#define MMCHS_SD_HCTL_SDBP_ON (0x1 << 8) /*SD Power on (start card detect?) */
#define MMCHS_SD_HCTL_SDVS (0x7 << 9) /*SD bus voltage select */
#define MMCHS_SD_HCTL_SDVS_VS18 (0x5 << 9) /*1.8 V */
#define MMCHS_SD_HCTL_SDVS_VS30 (0x6 << 9) /*3.0 V */
#define MMCHS_SD_HCTL_SDVS_VS33 (0x7 << 9) /*3.3 V */
#define MMCHS_SD_HCTL_IWE (0x1 << 24)/* wake-up event on SD interrupt */
#define MMCHS_SD_HCTL_IWE_DIS (0x0 << 24)/* Disable wake-up on SD interrupt */
#define MMCHS_SD_HCTL_IWE_EN (0x1 << 24)/* Enable wake-up on SD interrupt */
#define MMCHS_SD_SYSCTL_CLKD (0x3ff << 6) /* 10 bits clock frequency select */
#define MMCHS_SD_SYSCTL_SRD (0x1 << 26) /* Soft reset for mmc_dat line */
#define MMCHS_SD_SYSCTL_SRC (0x1 << 25) /* Soft reset for mmc_cmd line */
#define MMCHS_SD_SYSCTL_SRA (0x1 << 24) /* Soft reset all (host controller) */
#define MMCHS_SD_SYSCTL_ICE (0x1 << 0) /* Internal clock enable register */
#define MMCHS_SD_SYSCTL_ICE_DIS (0x0 << 0) /* Disable internal clock */
#define MMCHS_SD_SYSCTL_ICE_EN (0x1 << 0) /* Enable internal clock */
#define MMCHS_SD_SYSCTL_ICS (0x1 << 1) /* Internal clock stable register */
#define MMCHS_SD_SYSCTL_ICS_UNSTABLE (0x0 << 1) /* Internal clock is unstable */
#define MMCHS_SD_SYSCTL_ICS_STABLE (0x1 << 1) /* Internal clock is stable */
#define MMCHS_SD_SYSCTL_CEN (0x1 << 2) /* Card lock enable provide clock to the card */
#define MMCHS_SD_SYSCTL_CEN_DIS (0x0 << 2) /* Internal clock is unstable */
#define MMCHS_SD_SYSCTL_CEN_EN (0x1 << 2) /* Internal clock is stable */
#define MMCHS_SD_SYSCTL_DTO (0xf << 16) /* Data timeout counter */
#define MMCHS_SD_SYSCTL_DTO_2POW13 (0x0 << 16) /* TCF x 2^13 */
#define MMCHS_SD_SYSCTL_DTO_2POW14 (0x1 << 16) /* TCF x 2^14 */
#define MMCHS_SD_SYSCTL_DTO_2POW20 (0x7 << 16) /* TCF x 2^20 */
#define MMCHS_SD_SYSCTL_DTO_2POW27 (0xe << 16) /* TCF x 2^27 */
#define MMCHS_SD_STAT_CERR (0x1 << 28) /* card error */
#define MMCHS_SD_STAT_DEB (0x1 << 22) /* data end bit error */
#define MMCHS_SD_STAT_DCRC (0x1 << 21) /* data CRC error */
#define MMCHS_SD_STAT_DTO (0x1 << 20) /* data timeout error */
#define MMCHS_SD_STAT_CIE (0x1 << 19) /* command index error */
#define MMCHS_SD_STAT_CEB (0x1 << 18) /* command end bit error */
#define MMCHS_SD_STAT_CCRC (0x1 << 17) /* command CRC error */
#define MMCHS_SD_STAT_CTO (0x1 << 16) /* command timeout error */
#define MMCHS_SD_STAT_ERRI (0x01 << 15) /* Error interrupt */
#define MMCHS_SD_STAT_ERROR_MASK (0xff << 15 | 0x3 << 24 | 0x03 << 28)
#define MMCHS_SD_STAT_BRR (0x1 << 5) /* Buffer Read ready */
#define MMCHS_SD_STAT_BWR (0x1 << 4) /* Buffer Write ready */
#define MMCHS_SD_STAT_CC (0x1 << 0) /* Command complete status */
#define MMCHS_SD_STAT_CC_UNRAISED (0x0 << 0) /* Command not completed */
#define MMCHS_SD_STAT_CC_RAISED (0x1 << 0) /* Command completed */
#define MMCHS_SD_STAT_TC (0x1 << 1) /* Transfer complete status */
#define MMCHS_SD_STAT_TC_UNRAISED (0x0 << 1) /* Transfer not completed */
#define MMCHS_SD_STAT_TC_RAISED (0x1 << 1) /* Transfer completed */
#define MMCHS_SD_IE_ERROR_MASK (0xff << 15 | 0x3 << 24 | 0x03 << 28)
#define MMCHS_SD_IE_CC_ENABLE (0x1 << 0) /* Command complete interrupt enable */
#define MMCHS_SD_IE_CC_ENABLE_ENABLE (0x1 << 0) /* Command complete Interrupts are enabled */
#define MMCHS_SD_IE_CC_ENABLE_CLEAR (0x1 << 0) /* Clearing is done by writing a 0x1 */
#define MMCHS_SD_IE_TC_ENABLE (0x1 << 1) /* Transfer complete interrupt enable */
#define MMCHS_SD_IE_TC_ENABLE_ENABLE (0x1 << 1) /* Transfer complete Interrupts are enabled */
#define MMCHS_SD_IE_TC_ENABLE_CLEAR (0x1 << 1) /* Clearing TC is done by writing a 0x1 */
#define MMCHS_SD_IE_BRR_ENABLE (0x1 << 5) /* Buffer read ready interrupt */
#define MMCHS_SD_IE_BRR_ENABLE_DISABLE (0x0 << 5) /* Buffer read ready interrupt disable */
#define MMCHS_SD_IE_BRR_ENABLE_ENABLE (0x1 << 5) /* Buffer read ready interrupt enable */
#define MMCHS_SD_IE_BRR_ENABLE_CLEAR (0x1 << 5) /* Buffer read ready interrupt clear */
#define MMCHS_SD_IE_BWR_ENABLE (0x1 << 4) /* Buffer write ready interrupt */
#define MMCHS_SD_IE_BWR_ENABLE_DISABLE (0x0 << 4) /* Buffer write ready interrupt disable */
#define MMCHS_SD_IE_BWR_ENABLE_ENABLE (0x1 << 4) /* Buffer write ready interrupt enable */
#define MMCHS_SD_IE_BWR_ENABLE_CLEAR (0x1 << 4) /* Buffer write ready interrupt clear */
#define MMCHS_SD_CAPA_VS_MASK (0x7 << 24 ) /* voltage mask */
#define MMCHS_SD_CAPA_VS18 (0x01 << 26 ) /* 1.8 volt */
#define MMCHS_SD_CAPA_VS30 (0x01 << 25 ) /* 3.0 volt */
#define MMCHS_SD_CAPA_VS33 (0x01 << 24 ) /* 3.3 volt */
// The actual command indices
#define GO_IDLE_STATE 0
#define ALL_SEND_CID 2
#define SEND_RELATIVE_ADDR 3
#define SET_DSR 4
#define IO_SET_OP_COND 5
#define SWITCH_FUNC 6
#define SELECT_CARD 7
#define DESELECT_CARD 7
#define SELECT_DESELECT_CARD 7
#define SEND_IF_COND 8
#define SEND_CSD 9
#define SEND_CID 10
#define VOLTAGE_SWITCH 11
#define STOP_TRANSMISSION 12
#define SEND_STATUS 13
#define GO_INACTIVE_STATE 15
#define SET_BLOCKLEN 16
#define READ_SINGLE_BLOCK 17
#define READ_MULTIPLE_BLOCK 18
#define SEND_TUNING_BLOCK 19
#define SPEED_CLASS_CONTROL 20
#define SET_BLOCK_COUNT 23
#define WRITE_SINGLE_BLOCK 24
#define WRITE_MULTIPLE_BLOCK 25
#define PROGRAM_CSD 27
#define SET_WRITE_PROT 28
#define CLR_WRITE_PROT 29
#define SEND_WRITE_PROT 30
#define ERASE_WR_BLK_START 32
#define ERASE_WR_BLK_END 33
#define ERASE 38
#define LOCK_UNLOCK 42
#define APP_CMD 55
#define GEN_CMD 56
#define IS_APP_CMD 0x80000000
#define ACMD(a) (a | IS_APP_CMD)
#define SET_BUS_WIDTH (6 | IS_APP_CMD)
#define SD_STATUS (13 | IS_APP_CMD)
#define SEND_NUM_WR_BLOCKS (22 | IS_APP_CMD)
#define SET_WR_BLK_ERASE_COUNT (23 | IS_APP_CMD)
#define SD_SEND_OP_COND (41 | IS_APP_CMD)
#define SET_CLR_CARD_DETECT (42 | IS_APP_CMD)
#define SEND_SCR (51 | IS_APP_CMD)
#define SD_GET_CLOCK_DIVIDER_FAIL 0xffffffff
#define MIN_FREQ 400000
#define BCM2835_EMMC_WRITE_DELAY (((2 * 1000000) / MIN_FREQ) + 1)
// Enable 4-bit support
#define SD_4BIT_DATA
// Enable SDXC maximum performance mode
#define SDXC_MAXIMUM_PERFORMANCE
#endif

View File

@@ -1,202 +0,0 @@
/* $NetBSD: sdhcreg.h,v 1.6 2012/03/02 18:20:34 nonaka Exp $ */
/* $OpenBSD: sdhcreg.h,v 1.4 2006/07/30 17:20:40 fgsch Exp $ */
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _SDHCREG_H_
#define _SDHCREG_H_
/* Host standard register set */
#define SDHC_DMA_ADDR 0x00
#define SDHC_BLOCK_SIZE 0x04
#define SDHC_BLOCK_COUNT 0x06
#define SDHC_BLOCK_COUNT_MAX 512
#define SDHC_ARGUMENT 0x08
#define SDHC_TRANSFER_MODE 0x0c
#define SDHC_MULTI_BLOCK_MODE (1<<5)
#define SDHC_READ_MODE (1<<4)
#define SDHC_AUTO_CMD12_ENABLE (1<<2)
#define SDHC_BLOCK_COUNT_ENABLE (1<<1)
#define SDHC_DMA_ENABLE (1<<0)
#define SDHC_COMMAND 0x0e
/* 14-15 reserved */
#define SDHC_COMMAND_INDEX_SHIFT 8
#define SDHC_COMMAND_INDEX_MASK 0x3f
#define SDHC_COMMAND_TYPE_ABORT (3<<6)
#define SDHC_COMMAND_TYPE_RESUME (2<<6)
#define SDHC_COMMAND_TYPE_SUSPEND (1<<6)
#define SDHC_COMMAND_TYPE_NORMAL (0<<6)
#define SDHC_DATA_PRESENT_SELECT (1<<5)
#define SDHC_INDEX_CHECK_ENABLE (1<<4)
#define SDHC_CRC_CHECK_ENABLE (1<<3)
/* 2 reserved */
#define SDHC_RESP_LEN_48_CHK_BUSY (3<<0)
#define SDHC_RESP_LEN_48 (2<<0)
#define SDHC_RESP_LEN_136 (1<<0)
#define SDHC_NO_RESPONSE (0<<0)
#define SDHC_RESPONSE 0x10 /* - 0x1f */
#define SDHC_DATA 0x20
#define SDHC_PRESENT_STATE 0x24
/* 25-31 reserved */
#define SDHC_CMD_LINE_SIGNAL_LEVEL (1<<24)
#define SDHC_DAT3_LINE_LEVEL (1<<23)
#define SDHC_DAT2_LINE_LEVEL (1<<22)
#define SDHC_DAT1_LINE_LEVEL (1<<21)
#define SDHC_DAT0_LINE_LEVEL (1<<20)
#define SDHC_WRITE_PROTECT_SWITCH (1<<19)
#define SDHC_CARD_DETECT_PIN_LEVEL (1<<18)
#define SDHC_CARD_STATE_STABLE (1<<17)
#define SDHC_CARD_INSERTED (1<<16)
/* 12-15 reserved */
#define SDHC_BUFFER_READ_ENABLE (1<<11)
#define SDHC_BUFFER_WRITE_ENABLE (1<<10)
#define SDHC_READ_TRANSFER_ACTIVE (1<<9)
#define SDHC_WRITE_TRANSFER_ACTIVE (1<<8)
/* 3-7 reserved */
#define SDHC_DAT_ACTIVE (1<<2)
#define SDHC_CMD_INHIBIT_DAT (1<<1)
#define SDHC_CMD_INHIBIT_CMD (1<<0)
#define SDHC_CMD_INHIBIT_MASK 0x0003
#define SDHC_HOST_CTL 0x28
#define SDHC_HIGH_SPEED (1<<2)
#define SDHC_ESDHC_8BIT_MODE (1<<2) /* eSDHC */
#define SDHC_4BIT_MODE (1<<1)
#define SDHC_LED_ON (1<<0)
#define SDHC_POWER_CTL 0x29
#define SDHC_VOLTAGE_SHIFT 1
#define SDHC_VOLTAGE_MASK 0x07
#define SDHC_VOLTAGE_3_3V 0x07
#define SDHC_VOLTAGE_3_0V 0x06
#define SDHC_VOLTAGE_1_8V 0x05
#define SDHC_BUS_POWER (1<<0)
#define SDHC_BLOCK_GAP_CTL 0x2a
#define SDHC_WAKEUP_CTL 0x2b
#define SDHC_CLOCK_CTL 0x2c
#define SDHC_SDCLK_DIV_SHIFT 8
#define SDHC_SDCLK_DIV_MASK 0xff
#define SDHC_SDCLK_XDIV_SHIFT 6
#define SDHC_SDCLK_XDIV_MASK 0x3
#define SDHC_SDCLK_CGM (1<<5)
#define SDHC_SDCLK_DVS_SHIFT 4
#define SDHC_SDCLK_DVS_MASK 0xf
#define SDHC_SDCLK_ENABLE (1<<2)
#define SDHC_INTCLK_STABLE (1<<1)
#define SDHC_INTCLK_ENABLE (1<<0)
#define SDHC_TIMEOUT_CTL 0x2e
#define SDHC_TIMEOUT_MAX 0x0e
#define SDHC_SOFTWARE_RESET 0x2f
#define SDHC_INIT_ACTIVE (1<<3)
#define SDHC_RESET_MASK 0x5
#define SDHC_RESET_DAT (1<<2)
#define SDHC_RESET_CMD (1<<1)
#define SDHC_RESET_ALL (1<<0)
#define SDHC_NINTR_STATUS 0x30
#define SDHC_ERROR_INTERRUPT (1<<15)
#define SDHC_CARD_INTERRUPT (1<<8)
#define SDHC_CARD_REMOVAL (1<<7)
#define SDHC_CARD_INSERTION (1<<6)
#define SDHC_BUFFER_READ_READY (1<<5)
#define SDHC_BUFFER_WRITE_READY (1<<4)
#define SDHC_DMA_INTERRUPT (1<<3)
#define SDHC_BLOCK_GAP_EVENT (1<<2)
#define SDHC_TRANSFER_COMPLETE (1<<1)
#define SDHC_COMMAND_COMPLETE (1<<0)
#define SDHC_NINTR_STATUS_MASK 0x81ff
#define SDHC_EINTR_STATUS 0x32
#define SDHC_DMA_ERROR (1<<12)
#define SDHC_AUTO_CMD12_ERROR (1<<8)
#define SDHC_CURRENT_LIMIT_ERROR (1<<7)
#define SDHC_DATA_END_BIT_ERROR (1<<6)
#define SDHC_DATA_CRC_ERROR (1<<5)
#define SDHC_DATA_TIMEOUT_ERROR (1<<4)
#define SDHC_CMD_INDEX_ERROR (1<<3)
#define SDHC_CMD_END_BIT_ERROR (1<<2)
#define SDHC_CMD_CRC_ERROR (1<<1)
#define SDHC_CMD_TIMEOUT_ERROR (1<<0)
#define SDHC_EINTR_STATUS_MASK 0x01ff /* excluding vendor signals */
#define SDHC_NINTR_STATUS_EN 0x34
#define SDHC_EINTR_STATUS_EN 0x36
#define SDHC_NINTR_SIGNAL_EN 0x38
#define SDHC_NINTR_SIGNAL_MASK 0x01ff
#define SDHC_EINTR_SIGNAL_EN 0x3a
#define SDHC_EINTR_SIGNAL_MASK 0x01ff /* excluding vendor signals */
#define SDHC_CMD12_ERROR_STATUS 0x3c
#define SDHC_CAPABILITIES 0x40
#define SDHC_VOLTAGE_SUPP_1_8V (1<<26)
#define SDHC_VOLTAGE_SUPP_3_0V (1<<25)
#define SDHC_VOLTAGE_SUPP_3_3V (1<<24)
#define SDHC_DMA_SUPPORT (1<<22)
#define SDHC_HIGH_SPEED_SUPP (1<<21)
#define SDHC_MAX_BLK_LEN_512 0
#define SDHC_MAX_BLK_LEN_1024 1
#define SDHC_MAX_BLK_LEN_2048 2
#define SDHC_MAX_BLK_LEN_4096 3
#define SDHC_MAX_BLK_LEN_SHIFT 16
#define SDHC_MAX_BLK_LEN_MASK 0x3
#define SDHC_BASE_FREQ_SHIFT 8
#define SDHC_BASE_FREQ_MASK 0x3f
#define SDHC_TIMEOUT_FREQ_UNIT (1<<7) /* 0=KHz, 1=MHz */
#define SDHC_TIMEOUT_FREQ_SHIFT 0
#define SDHC_TIMEOUT_FREQ_MASK 0x1f
#define SDHC_MAX_CAPABILITIES 0x48
#define SDHC_HOST_VER 0xFC
#define SDHC_VVN_MASK 0x0f
#define SDHC_VVN_SHIFT 0x04
#define SDHC_SVN_MASK 0x0f
#define SDHC_SVN_SHIFT 0x00
#define SDHC_SLOT_INTR_STATUS 0xfc
#define SDHC_HOST_CTL_VERSION 0xfe
#define SDHC_SPEC_VERS_SHIFT 0
#define SDHC_SPEC_VERS_MASK 0xff
#define SDHC_VENDOR_VERS_SHIFT 8
#define SDHC_VENDOR_VERS_MASK 0xff
#define SDHC_DMA_CTL 0x40c /* eSDHC */
#define SDHC_DMA_SNOOP 0x40
/* SDHC_SPEC_VERS */
#define SDHC_SPEC_VERS_100 0x00
#define SDHC_SPEC_VERS_200 0x01
#define SDHC_SPEC_VERS_300 0x02
/* SDHC_CAPABILITIES decoding */
#define SDHC_BASE_FREQ_KHZ(cap) \
((((cap) >> SDHC_BASE_FREQ_SHIFT) & SDHC_BASE_FREQ_MASK) * 1000)
#define SDHC_TIMEOUT_FREQ(cap) \
(((cap) >> SDHC_TIMEOUT_FREQ_SHIFT) & SDHC_TIMEOUT_FREQ_MASK)
#define SDHC_TIMEOUT_FREQ_KHZ(cap) \
(((cap) & SDHC_TIMEOUT_FREQ_UNIT) ? \
SDHC_TIMEOUT_FREQ(cap) * 1000: \
SDHC_TIMEOUT_FREQ(cap))
/* SDHC_HOST_CTL_VERSION decoding */
#define SDHC_SPEC_VERSION(hcv) \
(((hcv) >> SDHC_SPEC_VERS_SHIFT) & SDHC_SPEC_VERS_MASK)
#define SDHC_VENDOR_VERSION(hcv) \
(((hcv) >> SDHC_VENDOR_VERS_SHIFT) & SDHC_VENDOR_VERS_MASK)
#define SDHC_PRESENT_STATE_BITS \
"\20\31CL\30D3L\27D2L\26D1L\25D0L\24WPS\23CD\22CSS\21CI" \
"\14BRE\13BWE\12RTA\11WTA\3DLA\2CID\1CIC"
#define SDHC_NINTR_STATUS_BITS \
"\20\20ERROR\11CARD\10REMOVAL\7INSERTION\6READ\5WRITE" \
"\4DMA\3GAP\2XFER\1CMD"
#define SDHC_EINTR_STATUS_BITS \
"\20\11ACMD12\10CL\7DEB\6DCRC\5DT\4CI\3CEB\2CCRC\1CT"
#define SDHC_CAPABILITIES_BITS \
"\20\33Vdd1.8V\32Vdd3.0V\31Vdd3.3V\30SUSPEND\27DMA\26HIGHSPEED"
#endif /* _SDHCREG_H_ */

View File

@@ -1,355 +0,0 @@
/* $NetBSD: sdmmcreg.h,v 1.8 2012/01/27 03:07:21 matt Exp $ */
/* $OpenBSD: sdmmcreg.h,v 1.4 2009/01/09 10:55:22 jsg Exp $ */
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _SDMMCREG_H_
#define _SDMMCREG_H_
/* MMC commands */ /* response type */
#define MMC_GO_IDLE_STATE 0 /* R0 */
#define MMC_SEND_OP_COND 1 /* R3 */
#define MMC_ALL_SEND_CID 2 /* R2 */
#define MMC_SET_RELATIVE_ADDR 3 /* R1 */
#define MMC_SWITCH 6 /* R1b */
#define MMC_SELECT_CARD 7 /* R1 */
#define MMC_SEND_EXT_CSD 8 /* R1 */
#define MMC_SEND_CSD 9 /* R2 */
#define MMC_SEND_CID 10 /* R2 */
#define MMC_STOP_TRANSMISSION 12 /* R1b */
#define MMC_SEND_STATUS 13 /* R1 */
#define MMC_INACTIVE_STATE 15 /* R0 */
#define MMC_SET_BLOCKLEN 16 /* R1 */
#define MMC_READ_BLOCK_SINGLE 17 /* R1 */
#define MMC_READ_BLOCK_MULTIPLE 18 /* R1 */
#define MMC_SET_BLOCK_COUNT 23 /* R1 */
#define MMC_WRITE_BLOCK_SINGLE 24 /* R1 */
#define MMC_WRITE_BLOCK_MULTIPLE 25 /* R1 */
#define MMC_PROGRAM_CSD 27 /* R1 */
#define MMC_SET_WRITE_PROT 28 /* R1b */
#define MMC_SET_CLR_WRITE_PROT 29 /* R1b */
#define MMC_SET_SEND_WRITE_PROT 30 /* R1 */
#define MMC_TAG_SECTOR_START 32 /* R1 */
#define MMC_TAG_SECTOR_END 33 /* R1 */
#define MMC_UNTAG_SECTOR 34 /* R1 */
#define MMC_TAG_ERASE_GROUP_START 35 /* R1 */
#define MMC_TAG_ERASE_GROUP_END 36 /* R1 */
#define MMC_UNTAG_ERASE_GROUP 37 /* R1 */
#define MMC_ERASE 38 /* R1b */
#define MMC_LOCK_UNLOCK 42 /* R1b */
#define MMC_APP_CMD 55 /* R1 */
#define MMC_READ_OCR 58 /* R3 */
/* SD commands */ /* response type */
#define SD_SEND_RELATIVE_ADDR 3 /* R6 */
#define SD_SEND_SWITCH_FUNC 6 /* R1 */
#define SD_SEND_IF_COND 8 /* R7 */
/* SD application commands */ /* response type */
#define SD_APP_SET_BUS_WIDTH 6 /* R1 */
#define SD_APP_OP_COND 41 /* R3 */
#define SD_APP_SEND_SCR 51 /* R1 */
/* OCR bits */
#define MMC_OCR_MEM_READY (1U<<31)/* memory power-up status bit */
#define MMC_OCR_HCS (1<<30)
#define MMC_OCR_3_5V_3_6V (1<<23)
#define MMC_OCR_3_4V_3_5V (1<<22)
#define MMC_OCR_3_3V_3_4V (1<<21)
#define MMC_OCR_3_2V_3_3V (1<<20)
#define MMC_OCR_3_1V_3_2V (1<<19)
#define MMC_OCR_3_0V_3_1V (1<<18)
#define MMC_OCR_2_9V_3_0V (1<<17)
#define MMC_OCR_2_8V_2_9V (1<<16)
#define MMC_OCR_2_7V_2_8V (1<<15)
#define MMC_OCR_2_6V_2_7V (1<<14)
#define MMC_OCR_2_5V_2_6V (1<<13)
#define MMC_OCR_2_4V_2_5V (1<<12)
#define MMC_OCR_2_3V_2_4V (1<<11)
#define MMC_OCR_2_2V_2_3V (1<<10)
#define MMC_OCR_2_1V_2_2V (1<<9)
#define MMC_OCR_2_0V_2_1V (1<<8)
#define MMC_OCR_1_9V_2_0V (1<<7)
#define MMC_OCR_1_8V_1_9V (1<<6)
#define MMC_OCR_1_7V_1_8V (1<<5)
#define MMC_OCR_1_6V_1_7V (1<<4)
/* R1 response type bits */
#define MMC_R1_READY_FOR_DATA (1<<8) /* ready for next transfer */
#define MMC_R1_APP_CMD (1<<5) /* app. commands supported */
/* 48-bit response decoding (32 bits w/o CRC) */
#define MMC_R1(resp) ((resp)[0])
#define MMC_R3(resp) ((resp)[0])
#define SD_R6(resp) ((resp)[0])
#define MMC_R7(resp) ((resp)[0])
#define MMC_SPI_R1(resp) ((resp)[0])
#define MMC_SPI_R7(resp) ((resp)[1])
/* RCA argument and response */
#define MMC_ARG_RCA(rca) ((rca) << 16)
#define SD_R6_RCA(resp) (SD_R6((resp)) >> 16)
/* bus width argument */
#define SD_ARG_BUS_WIDTH_1 0
#define SD_ARG_BUS_WIDTH_4 2
/* EXT_CSD fields */
#define EXT_CSD_BUS_WIDTH 183 /* WO */
#define EXT_CSD_HS_TIMING 185 /* R/W */
#define EXT_CSD_REV 192 /* RO */
#define EXT_CSD_STRUCTURE 194 /* RO */
#define EXT_CSD_CARD_TYPE 196 /* RO */
/* EXT_CSD field definitions */
#define EXT_CSD_CMD_SET_NORMAL (1U << 0)
#define EXT_CSD_CMD_SET_SECURE (1U << 1)
#define EXT_CSD_CMD_SET_CPSECURE (1U << 2)
/* EXT_CSD_BUS_WIDTH */
#define EXT_CSD_BUS_WIDTH_1 0 /* 1 bit mode */
#define EXT_CSD_BUS_WIDTH_4 1 /* 4 bit mode */
#define EXT_CSD_BUS_WIDTH_8 2 /* 8 bit mode */
/* EXT_CSD_STRUCTURE */
#define EXT_CSD_STRUCTURE_VER_1_0 0 /* CSD Version No.1.0 */
#define EXT_CSD_STRUCTURE_VER_1_1 1 /* CSD Version No.1.1 */
#define EXT_CSD_STRUCTURE_VER_1_2 2 /* Version 4.1-4.2-4.3 */
/* EXT_CSD_CARD_TYPE */
#define EXT_CSD_CARD_TYPE_26M (1 << 0)
#define EXT_CSD_CARD_TYPE_52M (1 << 1)
/* MMC_SWITCH access mode */
#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */
#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits in value */
#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits in value */
#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */
/* SPI mode reports R1/R2(SEND_STATUS) status. */
#define R1_SPI_IDLE (1 << 0)
#define R1_SPI_ERASE_RESET (1 << 1)
#define R1_SPI_ILLEGAL_COMMAND (1 << 2)
#define R1_SPI_COM_CRC (1 << 3)
#define R1_SPI_ERASE_SEQ (1 << 4)
#define R1_SPI_ADDRESS (1 << 5)
#define R1_SPI_PARAMETER (1 << 6)
/* R1 bit 7 is always zero */
#define R2_SPI_CARD_LOCKED (1 << 8)
#define R2_SPI_WP_ERASE_SKIP (1 << 9) /* or lock/unlock fail */
#define R2_SPI_LOCK_UNLOCK_FAIL R2_SPI_WP_ERASE_SKIP
#define R2_SPI_ERROR (1 << 10)
#define R2_SPI_CC_ERROR (1 << 11)
#define R2_SPI_CARD_ECC_ERROR (1 << 12)
#define R2_SPI_WP_VIOLATION (1 << 13)
#define R2_SPI_ERASE_PARAM (1 << 14)
#define R2_SPI_OUT_OF_RANGE (1 << 15) /* or CSD overwrite */
#define R2_SPI_CSD_OVERWRITE R2_SPI_OUT_OF_RANGE
/* MMC R2 response (CSD) */
#define MMC_CSD_CSDVER(resp) MMC_RSP_BITS((resp), 126, 2)
#define MMC_CSD_CSDVER_1_0 0
#define MMC_CSD_CSDVER_1_1 1
#define MMC_CSD_CSDVER_1_2 2 /* MMC 4.1 - 4.2 - 4.3 */
#define MMC_CSD_CSDVER_EXT_CSD 3 /* Version is coded in CSD_STRUCTURE in EXT_CSD */
#define MMC_CSD_MMCVER(resp) MMC_RSP_BITS((resp), 122, 4)
#define MMC_CSD_MMCVER_1_0 0 /* MMC 1.0 - 1.2 */
#define MMC_CSD_MMCVER_1_4 1 /* MMC 1.4 */
#define MMC_CSD_MMCVER_2_0 2 /* MMC 2.0 - 2.2 */
#define MMC_CSD_MMCVER_3_1 3 /* MMC 3.1 - 3.3 */
#define MMC_CSD_MMCVER_4_0 4 /* MMC 4.1 - 4.2 - 4.3 */
#define MMC_CSD_TAAC(resp) MMC_RSP_BITS((resp), 112, 8)
#define MMC_CSD_TAAC_MANT(resp) MMC_RSP_BITS((resp), 115, 4)
#define MMC_CSD_TAAC_EXP(resp) MMC_RSP_BITS((resp), 112, 3)
#define MMC_CSD_NSAC(resp) MMC_RSP_BITS((resp), 104, 8)
#define MMC_CSD_TRAN_SPEED(resp) MMC_RSP_BITS((resp), 96, 8)
#define MMC_CSD_TRAN_SPEED_MANT(resp) MMC_RSP_BITS((resp), 99, 4)
#define MMC_CSD_TRAN_SPEED_EXP(resp) MMC_RSP_BITS((resp), 96, 3)
#define MMC_CSD_READ_BL_LEN(resp) MMC_RSP_BITS((resp), 80, 4)
#define MMC_CSD_C_SIZE(resp) MMC_RSP_BITS((resp), 62, 12)
#define MMC_CSD_CAPACITY(resp) ((MMC_CSD_C_SIZE((resp))+1) << \
(MMC_CSD_C_SIZE_MULT((resp))+2))
#define MMC_CSD_C_SIZE_MULT(resp) MMC_RSP_BITS((resp), 47, 3)
#define MMC_CSD_R2W_FACTOR(resp) MMC_RSP_BITS((resp), 26, 3)
#define MMC_CSD_WRITE_BL_LEN(resp) MMC_RSP_BITS((resp), 22, 4)
/* MMC v1 R2 response (CID) */
#define MMC_CID_MID_V1(resp) MMC_RSP_BITS((resp), 104, 24)
#define MMC_CID_PNM_V1_CPY(resp, pnm) \
do { \
(pnm)[0] = MMC_RSP_BITS((resp), 96, 8); \
(pnm)[1] = MMC_RSP_BITS((resp), 88, 8); \
(pnm)[2] = MMC_RSP_BITS((resp), 80, 8); \
(pnm)[3] = MMC_RSP_BITS((resp), 72, 8); \
(pnm)[4] = MMC_RSP_BITS((resp), 64, 8); \
(pnm)[5] = MMC_RSP_BITS((resp), 56, 8); \
(pnm)[6] = MMC_RSP_BITS((resp), 48, 8); \
(pnm)[7] = '\0'; \
} while (/*CONSTCOND*/0)
#define MMC_CID_REV_V1(resp) MMC_RSP_BITS((resp), 40, 8)
#define MMC_CID_PSN_V1(resp) MMC_RSP_BITS((resp), 16, 24)
#define MMC_CID_MDT_V1(resp) MMC_RSP_BITS((resp), 8, 8)
/* MMC v2 R2 response (CID) */
#define MMC_CID_MID_V2(resp) MMC_RSP_BITS((resp), 120, 8)
#define MMC_CID_OID_V2(resp) MMC_RSP_BITS((resp), 104, 16)
#define MMC_CID_PNM_V2_CPY(resp, pnm) \
do { \
(pnm)[0] = MMC_RSP_BITS((resp), 96, 8); \
(pnm)[1] = MMC_RSP_BITS((resp), 88, 8); \
(pnm)[2] = MMC_RSP_BITS((resp), 80, 8); \
(pnm)[3] = MMC_RSP_BITS((resp), 72, 8); \
(pnm)[4] = MMC_RSP_BITS((resp), 64, 8); \
(pnm)[5] = MMC_RSP_BITS((resp), 56, 8); \
(pnm)[6] = '\0'; \
} while (/*CONSTCOND*/0)
#define MMC_CID_PSN_V2(resp) MMC_RSP_BITS((resp), 16, 32)
/* SD R2 response (CSD) */
#define SD_CSD_CSDVER(resp) MMC_RSP_BITS((resp), 126, 2)
#define SD_CSD_CSDVER_1_0 0
#define SD_CSD_CSDVER_2_0 1
#define SD_CSD_MMCVER(resp) MMC_RSP_BITS((resp), 122, 4)
#define SD_CSD_TAAC(resp) MMC_RSP_BITS((resp), 112, 8)
#define SD_CSD_TAAC_EXP(resp) MMC_RSP_BITS((resp), 115, 4)
#define SD_CSD_TAAC_MANT(resp) MMC_RSP_BITS((resp), 112, 3)
#define SD_CSD_TAAC_1_5_MSEC 0x26
#define SD_CSD_NSAC(resp) MMC_RSP_BITS((resp), 104, 8)
#define SD_CSD_SPEED(resp) MMC_RSP_BITS((resp), 96, 8)
#define SD_CSD_SPEED_MANT(resp) MMC_RSP_BITS((resp), 99, 4)
#define SD_CSD_SPEED_EXP(resp) MMC_RSP_BITS((resp), 96, 3)
#define SD_CSD_SPEED_25_MHZ 0x32
#define SD_CSD_SPEED_50_MHZ 0x5a
#define SD_CSD_CCC(resp) MMC_RSP_BITS((resp), 84, 12)
#define SD_CSD_CCC_BASIC (1 << 0) /* basic */
#define SD_CSD_CCC_BR (1 << 2) /* block read */
#define SD_CSD_CCC_BW (1 << 4) /* block write */
#define SD_CSD_CCC_ERACE (1 << 5) /* erase */
#define SD_CSD_CCC_WP (1 << 6) /* write protection */
#define SD_CSD_CCC_LC (1 << 7) /* lock card */
#define SD_CSD_CCC_AS (1 << 8) /*application specific*/
#define SD_CSD_CCC_IOM (1 << 9) /* I/O mode */
#define SD_CSD_CCC_SWITCH (1 << 10) /* switch */
#define SD_CSD_READ_BL_LEN(resp) MMC_RSP_BITS((resp), 80, 4)
#define SD_CSD_READ_BL_PARTIAL(resp) MMC_RSP_BITS((resp), 79, 1)
#define SD_CSD_WRITE_BLK_MISALIGN(resp) MMC_RSP_BITS((resp), 78, 1)
#define SD_CSD_READ_BLK_MISALIGN(resp) MMC_RSP_BITS((resp), 77, 1)
#define SD_CSD_DSR_IMP(resp) MMC_RSP_BITS((resp), 76, 1)
#define SD_CSD_C_SIZE(resp) MMC_RSP_BITS((resp), 62, 12)
#define SD_CSD_CAPACITY(resp) ((SD_CSD_C_SIZE((resp))+1) << \
(SD_CSD_C_SIZE_MULT((resp))+2))
#define SD_CSD_VDD_R_CURR_MIN(resp) MMC_RSP_BITS((resp), 59, 3)
#define SD_CSD_VDD_R_CURR_MAX(resp) MMC_RSP_BITS((resp), 56, 3)
#define SD_CSD_VDD_W_CURR_MIN(resp) MMC_RSP_BITS((resp), 53, 3)
#define SD_CSD_VDD_W_CURR_MAX(resp) MMC_RSP_BITS((resp), 50, 3)
#define SD_CSD_VDD_RW_CURR_100mA 0x7
#define SD_CSD_VDD_RW_CURR_80mA 0x6
#define SD_CSD_V2_C_SIZE(resp) MMC_RSP_BITS((resp), 48, 22)
#define SD_CSD_V2_CAPACITY(resp) ((SD_CSD_V2_C_SIZE((resp))+1) << 10)
#define SD_CSD_V2_BL_LEN 0x9 /* 512 */
#define SD_CSD_C_SIZE_MULT(resp) MMC_RSP_BITS((resp), 47, 3)
#define SD_CSD_ERASE_BLK_EN(resp) MMC_RSP_BITS((resp), 46, 1)
#define SD_CSD_SECTOR_SIZE(resp) MMC_RSP_BITS((resp), 39, 7) /* +1 */
#define SD_CSD_WP_GRP_SIZE(resp) MMC_RSP_BITS((resp), 32, 7) /* +1 */
#define SD_CSD_WP_GRP_ENABLE(resp) MMC_RSP_BITS((resp), 31, 1)
#define SD_CSD_R2W_FACTOR(resp) MMC_RSP_BITS((resp), 26, 3)
#define SD_CSD_WRITE_BL_LEN(resp) MMC_RSP_BITS((resp), 22, 4)
#define SD_CSD_RW_BL_LEN_2G 0xa
#define SD_CSD_RW_BL_LEN_1G 0x9
#define SD_CSD_WRITE_BL_PARTIAL(resp) MMC_RSP_BITS((resp), 21, 1)
#define SD_CSD_FILE_FORMAT_GRP(resp) MMC_RSP_BITS((resp), 15, 1)
#define SD_CSD_COPY(resp) MMC_RSP_BITS((resp), 14, 1)
#define SD_CSD_PERM_WRITE_PROTECT(resp) MMC_RSP_BITS((resp), 13, 1)
#define SD_CSD_TMP_WRITE_PROTECT(resp) MMC_RSP_BITS((resp), 12, 1)
#define SD_CSD_FILE_FORMAT(resp) MMC_RSP_BITS((resp), 10, 2)
/* SD R2 response (CID) */
#define SD_CID_MID(resp) MMC_RSP_BITS((resp), 120, 8)
#define SD_CID_OID(resp) MMC_RSP_BITS((resp), 104, 16)
#define SD_CID_PNM_CPY(resp, pnm) \
do { \
(pnm)[0] = MMC_RSP_BITS((resp), 96, 8); \
(pnm)[1] = MMC_RSP_BITS((resp), 88, 8); \
(pnm)[2] = MMC_RSP_BITS((resp), 80, 8); \
(pnm)[3] = MMC_RSP_BITS((resp), 72, 8); \
(pnm)[4] = MMC_RSP_BITS((resp), 64, 8); \
(pnm)[5] = '\0'; \
} while (/*CONSTCOND*/0)
#define SD_CID_REV(resp) MMC_RSP_BITS((resp), 56, 8)
#define SD_CID_PSN(resp) MMC_RSP_BITS((resp), 24, 32)
#define SD_CID_MDT(resp) MMC_RSP_BITS((resp), 8, 12)
/* SCR (SD Configuration Register) */
#define SCR_STRUCTURE(scr) MMC_RSP_BITS((scr), 60, 4)
#define SCR_STRUCTURE_VER_1_0 0 /* Version 1.0 */
#define SCR_SD_SPEC(scr) MMC_RSP_BITS((scr), 56, 4)
#define SCR_SD_SPEC_VER_1_0 0 /* Version 1.0 and 1.01 */
#define SCR_SD_SPEC_VER_1_10 1 /* Version 1.10 */
#define SCR_SD_SPEC_VER_2 2 /* Version 2.00 or Version 3.0X */
#define SCR_DATA_STAT_AFTER_ERASE(scr) MMC_RSP_BITS((scr), 55, 1)
#define SCR_SD_SECURITY(scr) MMC_RSP_BITS((scr), 52, 3)
#define SCR_SD_SECURITY_NONE 0 /* no security */
#define SCR_SD_SECURITY_1_0 1 /* security protocol 1.0 */
#define SCR_SD_SECURITY_1_0_2 2 /* security protocol 1.0 */
#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_RESERVED(scr) MMC_RSP_BITS((scr), 32, 16)
#define SCR_RESERVED2(scr) MMC_RSP_BITS((scr), 0, 32)
/* Status of Switch Function */
#define SFUNC_STATUS_GROUP(status, group) \
be16toh(__bitfield((uint32_t *)(status), (7 - (group)) << 4, 16))
/* Might be slow, but it should work on big and little endian systems. */
/* The macro used to do a (start)-8 to work around a bug in hardware see sdhc.c
* of the openbsd mmc code driver.
*/
#define MMC_RSP_BITS(resp, start, len) __bitfield((resp), (start), (len))
static inline int
__bitfield(uint32_t *src, int start, int len)
{
uint8_t *sp;
uint32_t dst, mask;
int shift, bs, bc;
if (start < 0 || len < 0 || len > 32)
return 0;
dst = 0;
mask = len % 32 ? UINT_MAX >> (32 - (len % 32)) : UINT_MAX;
shift = 0;
while (len > 0) {
sp = (uint8_t *)src + start / 8;
bs = start % 8;
bc = 8 - bs;
if (bc > len)
bc = len;
dst |= (*sp >> bs) << shift;
shift += bc;
start += bc;
len -= bc;
}
dst &= mask;
return (int)dst;
}
#endif /* _SDMMCREG_H_ */

View File

@@ -28,27 +28,29 @@ PROTO= proto
# Common to all architectures
ETC= system.conf group
EXTRA= rc
PROTO_FILES= proto.common.etc
PROTO_FILES+= proto.common.dynamic
PROTO_FILES= proto.common.etc
PROTO_FILES+= proto.common.dynamic
PROGRAMS= # defined
PROGRAMS+= fsck_mfs
dir.fsck_mfs:= minix/commands/fsck.mfs
PROGRAMS+= grep
dir.grep:= minix/usr.bin/grep
dir.grep:= minix/usr.bin/grep
PROGRAMS+= dd
dir.dd:= bin/dd
PROGRAMS+= input
dir.input:= minix/servers/input
dir.input:= minix/servers/input
PROGRAMS+= loadramdisk
dir.loadramdisk:= minix/commands/loadramdisk
PROGRAMS+= mfs
dir.mfs:= minix/fs/mfs
dir.mfs:= minix/fs/mfs
PROGRAMS+= mount
dir.mount:= minix/commands/mount
dir.mount:= minix/commands/mount
PROGRAMS+= procfs
dir.procfs:= minix/fs/procfs
PROGRAMS+= service
dir.service:= minix/commands/service
PROGRAMS+= sh
dir.sh:= bin/sh
dir.sh:= bin/sh
PROGRAMS+= sysenv
dir.sysenv:= minix/commands/sysenv
PROGRAMS+= umount
@@ -65,9 +67,9 @@ dir.at_wini:= minix/drivers/storage/at_wini
PROGRAMS+= floppy
dir.floppy:= minix/drivers/storage/floppy
PROGRAMS+= pci
dir.pci:= minix/drivers/bus/pci
dir.pci:= minix/drivers/bus/pci
PROGRAMS+= pckbd
dir.pckbd:= minix/drivers/hid/pckbd
dir.pckbd:= minix/drivers/hid/pckbd
PROGRAMS+= cdprobe
dir.cdprobe:= minix/commands/cdprobe
PROGRAMS+= pwd_mkdb
@@ -77,23 +79,25 @@ dir.isofs:= minix/fs/isofs
.if ${MKSMALL} != "yes"
PROGRAMS+= ahci
dir.ahci:= minix/drivers/storage/ahci
dir.ahci:= minix/drivers/storage/ahci
PROGRAMS+= virtio_blk
dir.virtio_blk:= minix/drivers/storage/virtio_blk
PROGRAMS+= ext2
dir.ext2:= minix/fs/ext2
dir.ext2:= minix/fs/ext2
.endif
.if ${MKACPI} != "no"
RAMDISK_INC_ACPI= 1
PROGRAMS+= acpi
dir.acpi:= minix/drivers/power/acpi
dir.acpi:= minix/drivers/power/acpi
.endif
.endif # ${MACHINE_ARCH} == "i386"
.if ${MACHINE_ARCH} == "earm"
PROGRAMS+= mmc
dir.mmc:= minix/drivers/storage/mmc
PROGRAMS+= rpi_mmc
dir.rpi_mmc:= minix/drivers/storage/mmc/rpi
PROGRAMS+= omap_mmc
dir.omap_mmc:= minix/drivers/storage/mmc/omap
.endif # ${MACHINE_ARCH} == "earm"
.if ${LDSTATIC} == "-dynamic"

View File

@@ -12,6 +12,7 @@ d--755 0 0
mount ---755 0 0 mount
umount ---755 0 0 umount
grep ---755 0 0 grep
dd ---755 0 0 dd
sh ---755 0 0 sh
service ---755 0 0 service
$
@@ -28,7 +29,8 @@ d--755 0 0
isofs ---755 0 0 isofs
#endif
#ifdef __arm__
mmc ---755 0 0 mmc
rpi_mmc ---755 0 0 rpi_mmc
omap_mmc ---755 0 0 omap_mmc
#endif
mfs ---755 0 0 mfs
procfs ---755 0 0 procfs

View File

@@ -53,7 +53,7 @@ fi
if [ X`/bin/sysenv arch` = Xearm ]
then echo Starting the mmc driver
/bin/service -c up /service/mmc -dev /dev/c0d0
/bin/service -c up /service/rpi_mmc -dev /dev/c0d0
fi
/bin/service up /service/procfs || echo "WARNING: couldn't start procfs"