Lee Leahy has uploaded a new change for review. ( https://review.coreboot.org/19007 )
Change subject: drivers/storage: Get SD/MMC driver to build ......................................................................
drivers/storage: Get SD/MMC driver to build
Add the Kconfig and Makefile and make necessary edits to get the code to build.
TEST=Build for reef
Change-Id: I0cce2d3001ab1b3d7bbbb37f07001eef50af1924 Signed-off-by: Lee Leahy Leroy.P.Leahy@intel.com --- A src/drivers/storage/Kconfig A src/drivers/storage/Makefile.inc M src/drivers/storage/mmc.c M src/drivers/storage/sdhci.c A src/drivers/storage/storage.h M src/include/device/mmc.h M src/include/device/sdhci.h 7 files changed, 206 insertions(+), 149 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/07/19007/1
diff --git a/src/drivers/storage/Kconfig b/src/drivers/storage/Kconfig new file mode 100644 index 0000000..2546eea --- /dev/null +++ b/src/drivers/storage/Kconfig @@ -0,0 +1,34 @@ +## +## This file is part of the coreboot project. +## +## Copyright (C) 2017 Intel Corp. +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; version 2 of the License. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## + +config DRIVERS_STORAGE + bool + default n + +if DRIVERS_STORAGE + +config MMC_DEBUG + bool "Debug SD/MMC host controller" + default n + help + Display clock speed and bus width settings + +config MMC_TRACE + bool "Trace the MMC operations" + default n + help + Display MMC commands and responses + +endif # DRIVERS_STORAGE diff --git a/src/drivers/storage/Makefile.inc b/src/drivers/storage/Makefile.inc new file mode 100644 index 0000000..79957ac --- /dev/null +++ b/src/drivers/storage/Makefile.inc @@ -0,0 +1,21 @@ +# +# This file is part of the coreboot project. +# +# Copyright (C) 2017 Intel Corporation. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# + +ifeq ($(CONFIG_DRIVERS_STORAGE),y) + +ramstage-y += mmc.c +ramstage-y += sdhci.c + +endif # CONFIG_DRIVERS_STORAGE diff --git a/src/drivers/storage/mmc.c b/src/drivers/storage/mmc.c index 9338f8f..a5394e3 100644 --- a/src/drivers/storage/mmc.c +++ b/src/drivers/storage/mmc.c @@ -22,32 +22,34 @@ */
#include <assert.h> +#include <delay.h> #include <device/mmc.h> +#include <device/sdhci.h> #include <endian.h> -#include <libpayload.h> -#include <stdint.h> - -#include "config.h" +#include "storage.h" +#include <string.h> +#include <timer.h>
/* Set block count limit because of 16 bit register limit on some hardware*/ #ifndef CONFIG_SYS_MMC_MAX_BLK_COUNT #define CONFIG_SYS_MMC_MAX_BLK_COUNT 65535 #endif
-/* Set to 1 to turn on debug messages. */ -int __mmc_debug = 0; -int __mmc_trace = 0; - int mmc_busy_wait_io(volatile uint32_t *address, uint32_t *output, uint32_t io_mask, uint32_t timeout_ms) { uint32_t value = (uint32_t)-1; - uint64_t start = timer_us(0); + struct mono_time current, end; + + timer_monotonic_get(¤t); + end = current; + mono_time_add_msecs(&end, timeout_ms);
if (!output) output = &value; for (; *output & io_mask; *output = readl(address)) { - if (timer_us(start) > timeout_ms * 1000) + timer_monotonic_get(¤t); + if (mono_time_after(¤t, &end)) return -1; } return 0; @@ -57,12 +59,17 @@ uint32_t io_mask, uint32_t timeout_ms) { uint32_t value = 0; - uint64_t start = timer_us(0); + struct mono_time current, end; + + timer_monotonic_get(¤t); + end = current; + mono_time_add_msecs(&end, timeout_ms);
if (!output) output = &value; for (; !(*output & io_mask); *output = readl(address)) { - if (timer_us(start) > timeout_ms * 1000) + timer_monotonic_get(¤t); + if (mono_time_after(¤t, &end)) return -1; } return 0; @@ -280,7 +287,7 @@ static int mmc_go_idle(MmcMedia *media) { // Some cards can't accept idle commands without delay. - if (media->dev.removable) + if (media->removable) mdelay(1);
MmcCommand cmd; @@ -295,7 +302,7 @@
// Some cards need more than half second to respond to next command (ex, // SEND_OP_COND). - if (media->dev.removable) + if (media->removable) mdelay(2);
return 0; @@ -407,10 +414,13 @@ { MmcCommand cmd;
- int timeout = MMC_INIT_TIMEOUT_US; - uint64_t start; + int timeout = MMC_INIT_TIMEOUT_US_MS; + struct mono_time current, end;
- start = timer_us(0); + timer_monotonic_get(¤t); + end = current; + mono_time_add_msecs(&end, timeout); + while (1) { // CMD1 queries whether initialization is done. int err = mmc_send_op_cond_iter(media, &cmd, 1); @@ -422,7 +432,8 @@ break;
// Check if init timeout has expired. - if (timer_us(start) > timeout) + timer_monotonic_get(¤t); + if (mono_time_after(¤t, &end)) return MMC_UNUSABLE_ERR;
udelay(100); @@ -707,8 +718,8 @@ } mmc_debug("%s: end SD_CMD_APP_SEND_SCR\n", __func__);
- media->scr[0] = betohl(scr[0]); - media->scr[1] = betohl(scr[1]); + media->scr[0] = be32toh(scr[0]); + media->scr[1] = be32toh(scr[1]);
switch ((media->scr[0] >> 24) & 0xf) { case 0: @@ -1009,8 +1020,8 @@ } }
- media->dev.block_count = media->capacity / media->read_bl_len; - media->dev.block_size = media->read_bl_len; + media->block_count = media->capacity / media->read_bl_len; + media->block_size = media->read_bl_len;
printf("Man %06x Snr %u ", media->cid[0] >> 24, @@ -1062,7 +1073,8 @@ { int err;
- MmcMedia *media = xzalloc(sizeof(*media)); + MmcMedia *media = malloc(sizeof(*media)); + memset(media, 0, sizeof(*media)); media->ctrlr = ctrlr;
mmc_set_bus_width(ctrlr, 1); @@ -1115,27 +1127,21 @@ ///////////////////////////////////////////////////////////////////////////// // BlockDevice utilities and callbacks
-static inline MmcMedia *mmc_media(BlockDevOps *me) -{ - return container_of(me, MmcMedia, dev.ops); -} - static inline MmcCtrlr *mmc_ctrlr(MmcMedia *media) { return media->ctrlr; }
-static int block_mmc_setup(BlockDevOps *me, lba_t start, lba_t count, +static int block_mmc_setup(MmcMedia *media, lba_t start, lba_t count, int is_read) { - MmcMedia *media = mmc_media(me); MmcCtrlr *ctrlr = mmc_ctrlr(media);
if (count == 0) return 0;
- if (start > media->dev.block_count || - start + count > media->dev.block_count) + if (start > media->block_count || + start + count > media->block_count) return 0;
uint32_t bl_len = is_read ? media->read_bl_len : @@ -1156,15 +1162,14 @@ return 1; }
-lba_t block_mmc_read(BlockDevOps *me, lba_t start, lba_t count, void *buffer) +lba_t block_mmc_read(MmcMedia *media, lba_t start, lba_t count, void *buffer) { uint8_t *dest = (uint8_t *)buffer;
- if (block_mmc_setup(me, start, count, 1) == 0) + if (block_mmc_setup(media, start, count, 1) == 0) return 0;
lba_t todo = count; - MmcMedia *media = mmc_media(me); MmcCtrlr *ctrlr = mmc_ctrlr(media); do { lba_t cur = MIN(todo, ctrlr->b_max); @@ -1179,16 +1184,15 @@ return count; }
-lba_t block_mmc_write(BlockDevOps *me, lba_t start, lba_t count, +lba_t block_mmc_write(MmcMedia *media, lba_t start, lba_t count, const void *buffer) { const uint8_t *src = (const uint8_t *)buffer;
- if (block_mmc_setup(me, start, count, 0) == 0) + if (block_mmc_setup(media, start, count, 0) == 0) return 0;
lba_t todo = count; - MmcMedia *media = mmc_media(me); MmcCtrlr *ctrlr = mmc_ctrlr(media); do { lba_t cur = MIN(todo, ctrlr->b_max); @@ -1201,14 +1205,13 @@ return count; }
-lba_t block_mmc_erase(BlockDevOps *me, lba_t start, lba_t count) +lba_t block_mmc_erase(MmcMedia *media, lba_t start, lba_t count) { MmcCommand cmd;
- if (block_mmc_setup(me, start, count, 0) == 0) + if (block_mmc_setup(media, start, count, 0) == 0) return 0;
- MmcMedia *media = mmc_media(me); MmcCtrlr *ctrlr = mmc_ctrlr(media);
cmd.cmdidx = MMC_CMD_ERASE_GROUP_START; @@ -1272,15 +1275,14 @@ return count; }
-lba_t block_mmc_fill_write(BlockDevOps *me, lba_t start, lba_t count, +lba_t block_mmc_fill_write(MmcMedia *media, lba_t start, lba_t count, uint32_t fill_pattern) { - if (block_mmc_setup(me, start, count, 0) == 0) + if (block_mmc_setup(media, start, count, 0) == 0) return 0;
- MmcMedia *media = mmc_media(me); MmcCtrlr *ctrlr = mmc_ctrlr(media); - uint64_t block_size = media->dev.block_size; + uint64_t block_size = media->block_size; /* * We allocate max 4 MiB buffer on heap and set it to fill_pattern and * perform mmc_write operation using this 4MiB buffer until requested @@ -1305,7 +1307,7 @@
uint64_t buffer_bytes = buffer_lba * block_size; uint64_t buffer_words = buffer_bytes / sizeof(uint32_t); - uint32_t *buffer = xmalloc(buffer_bytes); + uint32_t *buffer = malloc(buffer_bytes); uint32_t *ptr = buffer;
for ( ; buffer_words ; buffer_words--) diff --git a/src/drivers/storage/sdhci.c b/src/drivers/storage/sdhci.c index f655849..d16b324 100644 --- a/src/drivers/storage/sdhci.c +++ b/src/drivers/storage/sdhci.c @@ -21,21 +21,31 @@ * Murray.Jensen@cmst.csiro.au, 27-Jan-01. */
+#include <assert.h> +#include <delay.h> #include <device/mmc.h> #include <device/sdhci.h> -#include <libpayload.h> - -#include "drivers/storage/blockdev.h" +#include <endian.h> +#include "storage.h" +#include <string.h> +#include <timer.h>
static void sdhci_reset(SdhciHost *host, u8 mask) { unsigned long timeout; + struct mono_time current, end;
/* Wait max 100 ms */ timeout = 100; + + timer_monotonic_get(¤t); + end = current; + mono_time_add_msecs(&end, timeout); + sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET); while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) { - if (timeout == 0) { + timer_monotonic_get(¤t); + if (mono_time_after(¤t, &end)) { printf("Reset 0x%x never completed.\n", (int)mask); return; } @@ -120,7 +130,7 @@
/* use dma_malloc() to make sure we get the coherent/uncached memory */ if (!host->adma_descs) { - host->adma_descs = dma_malloc(need_descriptors * + host->adma_descs = malloc(need_descriptors * sizeof(*host->adma_descs)); if (host->adma_descs == NULL) die("fail to malloc adma_descs\n"); @@ -144,7 +154,7 @@
/* use dma_malloc() to make sure we get the coherent/uncached memory */ if (!host->adma64_descs) { - host->adma64_descs = dma_malloc(need_descriptors * + host->adma64_descs = malloc(need_descriptors * sizeof(*host->adma64_descs)); if (host->adma64_descs == NULL) die("fail to malloc adma64_descs\n"); @@ -156,8 +166,7 @@ need_descriptors); }
-static int sdhci_setup_adma(SdhciHost *host, MmcData *data, - struct bounce_buffer *bbstate) +static int sdhci_setup_adma(SdhciHost *host, MmcData *data) { int i, togo, need_descriptors; char *buffer_data; @@ -176,11 +185,7 @@ sdhci_alloc_adma64_descs(host, need_descriptors); else sdhci_alloc_adma_descs(host, need_descriptors); - - if (bbstate) - buffer_data = (char *)bbstate->bounce_buffer; - else - buffer_data = data->dest; + buffer_data = data->dest;
/* Now set up the descriptor chain. */ for (i = 0; togo; i++) { @@ -271,15 +276,14 @@ return MMC_COMM_ERR; }
-static int sdhci_send_command_bounced(MmcCtrlr *mmc_ctrl, MmcCommand *cmd, - MmcData *data, - struct bounce_buffer *bbstate) +static int sdhci_send_command(MmcCtrlr *mmc_ctrl, MmcCommand *cmd, + MmcData *data) { unsigned int stat = 0; int ret = 0; u32 mask, flags; unsigned int timeout, start_addr = 0; - uint64_t start; + struct mono_time current, end; SdhciHost *host = container_of(mmc_ctrl, SdhciHost, mmc_ctrlr);
/* Wait max 1 s */ @@ -340,7 +344,7 @@ sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT);
if (host->host_caps & MMC_AUTO_CMD12) { - if (sdhci_setup_adma(host, data, bbstate)) + if (sdhci_setup_adma(host, data)) return -1;
mode |= SDHCI_TRNS_DMA; @@ -354,7 +358,10 @@ if (data && (host->host_caps & MMC_AUTO_CMD12)) return sdhci_complete_adma(host, cmd);
- start = timer_us(0); + timer_monotonic_get(¤t); + end = current; + mono_time_add_msecs(&end, 2550); + do { stat = sdhci_readl(host, SDHCI_INT_STATUS); if (stat & SDHCI_INT_ERROR) @@ -362,7 +369,8 @@
/* Apply max timeout for R1b-type CMD defined in eMMC ext_csd except for erase ones */ - if (timer_us(start) > 2550000) { + timer_monotonic_get(¤t); + if (mono_time_after(¤t, &end)) { if (host->quirks & SDHCI_QUIRK_BROKEN_R1B) return 0; else { @@ -394,50 +402,7 @@ sdhci_reset(host, SDHCI_RESET_DATA); if (stat & SDHCI_INT_TIMEOUT) return MMC_TIMEOUT; - else - return MMC_COMM_ERR; -} - -static int sdhci_send_command(MmcCtrlr *mmc_ctrl, MmcCommand *cmd, - MmcData *data) -{ - void *buf; - unsigned int bbflags; - size_t len; - struct bounce_buffer *bbstate = NULL; - struct bounce_buffer bbstate_val; - int ret; - - if (data) { - if (data->flags & MMC_DATA_READ) { - buf = data->dest; - bbflags = GEN_BB_WRITE; - } else { - buf = (void *)data->src; - bbflags = GEN_BB_READ; - } - len = data->blocks * data->blocksize; - - /* - * on some platform(like rk3399 etc) need to worry about - * cache coherency, so check the buffer, if not dma - * coherent, use bounce_buffer to do DMA management. - */ - if (!dma_coherent(buf)) { - bbstate = &bbstate_val; - if (bounce_buffer_start(bbstate, buf, len, bbflags)) { - printf("ERROR: Failed to get bounce buffer.\n"); - return -1; - } - } - } - - ret = sdhci_send_command_bounced(mmc_ctrl, cmd, data, bbstate); - - if (bbstate) - bounce_buffer_stop(bbstate); - - return ret; + return MMC_COMM_ERR; }
static int sdhci_set_clock(SdhciHost *host, unsigned int clock) @@ -557,7 +522,7 @@ sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); }
-void sdhci_set_uhs_signaling(SdhciHost *host, uint32_t timing) +static void sdhci_set_uhs_signaling(SdhciHost *host, uint32_t timing) { u16 ctrl_2;
@@ -589,7 +554,7 @@ sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); }
-void sdhci_set_ios(MmcCtrlr *mmc_ctrlr) +static void sdhci_set_ios(MmcCtrlr *mmc_ctrlr) { u32 ctrl; SdhciHost *host = container_of(mmc_ctrlr, @@ -763,11 +728,8 @@ return 0; }
-static int sdhci_update(BlockDevCtrlrOps *me) +static int sdhci_update(SdhciHost *host) { - SdhciHost *host = container_of - (me, SdhciHost, mmc_ctrlr.ctrlr.ops); - if (host->removable) { int present = (sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT) != 0; @@ -778,8 +740,6 @@ * A card was present but isn't any more. Get * rid of it. */ - list_remove - (&host->mmc_ctrlr.media->dev.list_node); free(host->mmc_ctrlr.media); host->mmc_ctrlr.media = NULL; } @@ -795,10 +755,6 @@
if (mmc_setup_media(&host->mmc_ctrlr)) return -1; - host->mmc_ctrlr.media->dev.name = "SDHCI card"; - list_insert_after - (&host-> mmc_ctrlr.media->dev.list_node, - &removable_block_devices); } } else { if (!host->initialized && sdhci_init(host)) @@ -808,28 +764,20 @@
if (mmc_setup_media(&host->mmc_ctrlr)) return -1; - host->mmc_ctrlr.media->dev.name = "SDHCI fixed"; - list_insert_after(&host->mmc_ctrlr.media->dev.list_node, - &fixed_block_devices); - host->mmc_ctrlr.ctrlr.need_update = 0; }
- host->mmc_ctrlr.media->dev.removable = host->removable; - host->mmc_ctrlr.media->dev.ops.read = block_mmc_read; - host->mmc_ctrlr.media->dev.ops.write = block_mmc_write; - host->mmc_ctrlr.media->dev.ops.new_stream = new_simple_stream; - + host->mmc_ctrlr.media->removable = host->removable; return 0; }
-void add_sdhci(SdhciHost *host) +int add_sdhci(SdhciHost *host) { host->mmc_ctrlr.send_cmd = &sdhci_send_command; host->mmc_ctrlr.set_ios = &sdhci_set_ios;
- host->mmc_ctrlr.ctrlr.ops.update = &sdhci_update; - host->mmc_ctrlr.ctrlr.need_update = 1; - /* TODO(vbendeb): check if SDHCI spec allows to retrieve this value. */ host->mmc_ctrlr.b_max = 65535; + + /* Initialize the SDHC controller */ + return sdhci_update(host); } diff --git a/src/drivers/storage/storage.h b/src/drivers/storage/storage.h new file mode 100644 index 0000000..6ec5ada --- /dev/null +++ b/src/drivers/storage/storage.h @@ -0,0 +1,33 @@ +/* + * Copyrigit 2017 Intel Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __DRIVERS_STORAGE_STORAGE_H__ +#define __DRIVERS_STORAGE_STORAGE_H__ + +#include <stdint.h> + +#define DMA_MINALIGN (64) +#define ROUND(a,b) (((a) + (b) - 1) & ~((b) - 1)) +#define ALLOC_CACHE_ALIGN_BUFFER(type, name, size) \ + char __##name[ROUND(size * sizeof(type), DMA_MINALIGN) + \ + DMA_MINALIGN - 1]; \ + type *name = (type *) ALIGN((uintptr_t)__##name, DMA_MINALIGN) + +/* NOOPs mirroring ARM's cache API, since x86 devices usually cache snoop */ +#define dcache_invalidate_by_mva(addr, len) +#define dcache_clean_invalidate_by_mva(addr, len) + +#define printf(fmt, args...) printk(BIOS_DEBUG, fmt, ##args) + +#endif /* __DRIVERS_STORAGE_STORAGE_H__ */ diff --git a/src/include/device/mmc.h b/src/include/device/mmc.h index 67e9962..fa74ec4 100644 --- a/src/include/device/mmc.h +++ b/src/include/device/mmc.h @@ -24,8 +24,7 @@ #ifndef __DEVICE_MMC_H__ #define __DEVICE_MMC_H__
-#include "drivers/storage/blockdev.h" -#include "drivers/storage/bouncebuf.h" +#include <stdint.h>
#define SD_VERSION_SD 0x20000 #define SD_VERSION_2 (SD_VERSION_SD | 0x20) @@ -215,6 +214,7 @@ #define MMC_RSP_R7 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
#define MMC_INIT_TIMEOUT_US (1000 * 1000) +#define MMC_INIT_TIMEOUT_US_MS 1000 #define MMC_IO_RETRIES (1000) #define MMC_CLOCK_20MHZ (20000000) #define MMC_CLOCK_25MHZ (25000000) @@ -248,8 +248,6 @@ typedef struct MmcMedia MmcMedia;
typedef struct MmcCtrlr { - BlockDevCtrlr ctrlr; - MmcMedia *media;
uint32_t voltages; @@ -286,8 +284,9 @@ } MmcCtrlr;
typedef struct MmcMedia { - BlockDev dev; - + uint64_t block_count; + uint32_t block_size; + int removable; MmcCtrlr *ctrlr;
uint32_t caps; @@ -318,15 +317,20 @@
int mmc_setup_media(MmcCtrlr *ctrlr);
-lba_t block_mmc_read(BlockDevOps *me, lba_t start, lba_t count, void *buffer); -lba_t block_mmc_write(BlockDevOps *me, lba_t start, lba_t count, +typedef uint64_t lba_t; + +lba_t block_mmc_read(MmcMedia *media, lba_t start, lba_t count, void *buffer); +lba_t block_mmc_write(MmcMedia *media, lba_t start, lba_t count, const void *buffer); -lba_t block_mmc_erase(BlockDevOps *me, lba_t start, lba_t count); -lba_t block_mmc_fill_write(BlockDevOps *me, lba_t start, lba_t count, +lba_t block_mmc_erase(MmcMedia *media, lba_t start, lba_t count); +lba_t block_mmc_fill_write(MmcMedia *media, lba_t start, lba_t count, uint32_t fill_pattern);
+/* Select the corresponding CONFIG variable to turn on debug/trace messages */ +#define __mmc_debug (IS_ENABLED(CONFIG_MMC_DEBUG)) +#define __mmc_trace (IS_ENABLED(CONFIG_MMC_TRACE)) + // Debug functions. -extern int __mmc_debug, __mmc_trace; #define mmc_debug(format...) \ while (__mmc_debug) { printf("mmc: " format); break; } #define mmc_trace(format...) \ diff --git a/src/include/device/sdhci.h b/src/include/device/sdhci.h index 42e50c3..55aa559 100644 --- a/src/include/device/sdhci.h +++ b/src/include/device/sdhci.h @@ -23,8 +23,14 @@ #ifndef __DEVICE_SDHCI_H__ #define __DEVICE_SDHCI_H__
+#ifndef __SIMPLE_DEVICE__ +#define __SIMPLE_DEVICE__ 1 +#endif /* __SIMPLE_DEVICE__ */ +#include <device/device.h> #include <device/mmc.h> -#include <libpayload.h> +#include <device/pci.h> +#include <device/pci_def.h> +#include <device/pci_ops.h>
/* * Controller registers @@ -317,6 +323,14 @@ void (*set_control_reg)(SdhciHost *host); };
+#define readb(_a) (*(volatile const unsigned char *) (_a)) +#define readw(_a) (*(volatile const unsigned short *) (_a)) +#define readl(_a) (*(volatile const unsigned int *) (_a)) + +#define writeb(_v, _a) (*(volatile unsigned char *) (_a) = (_v)) +#define writew(_v, _a) (*(volatile unsigned short *) (_a) = (_v)) +#define writel(_v, _a) (*(volatile unsigned int *) (_a) = (_v)) + static inline void sdhci_writel(SdhciHost *host, u32 val, int reg) { writel(val, host->ioaddr + reg); @@ -346,8 +360,9 @@ return readb(host->ioaddr + reg); }
-void add_sdhci(SdhciHost *host); -void sdhci_set_ios(MmcCtrlr *mmc_ctrlr); +int add_sdhci(SdhciHost *host); + +typedef uint32_t pcidev_t;
/* Add SDHCI controller from PCI */ SdhciHost *new_pci_sdhci_host(pcidev_t dev,