o Don't allocate resources for SDMA in sdhci(4) if the controller or the

front-end doesn't support SDMA or the latter implements a platform-
  specific transfer method instead. While at it, factor out allocation
  and freeing of SDMA resources to sdhci_dma_{alloc,free}() in order to
  keep the code more readable when adding support for ADMA variants.

o Base the size of the SDMA bounce buffer on MAXPHYS up to the maximum
  of 512 KiB instead of using a fixed 4-KiB-buffer. With the default
  MAXPHYS of 128 KiB and depending on the controller and medium, this
  reduces the number of SDHCI interrupts by a factor of ~16 to ~32 on
  sequential reads while an increase of throughput of up to ~84 % was
  seen.

  Front-ends for broken controllers that only support an SDMA buffer
  boundary of a specific size may set SDHCI_QUIRK_BROKEN_SDMA_BOUNDARY
  and supply a size via struct sdhci_slot. According to Linux, only
  Qualcomm MSM-type SDHCI controllers are affected by this, though.

  Requested by: Shreyank Amartya (unconditional bump to 512 KiB)

o Introduce a SDHCI_DEPEND macro for specifying the dependency of the
  front-end modules on the sdhci(4) one and bump the module version
  of sdhci(4) to 2 via an also newly introduced SDHCI_VERSION in order
  to ensure that all components are in sync WRT struct sdhci_slot.

o In sdhci(4):
  - Make pointers const were applicable,
  - replace a few device_printf(9) calls with slot_printf() for
    consistency, and
  - sync some local functions with their prototypes WRT static.
This commit is contained in:
Marius Strobl 2018-12-30 23:08:06 +00:00
parent 55d621a104
commit ab00a509ee
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=342634
11 changed files with 185 additions and 108 deletions

View File

@ -683,7 +683,7 @@ static driver_t bcm_sdhci_driver = {
DRIVER_MODULE(sdhci_bcm, simplebus, bcm_sdhci_driver, bcm_sdhci_devclass,
NULL, NULL);
MODULE_DEPEND(sdhci_bcm, sdhci, 1, 1, 1);
SDHCI_DEPEND(sdhci_bcm);
#ifndef MMCCAM
MMC_DECLARE_BRIDGE(sdhci_bcm);
#endif

View File

@ -1287,7 +1287,7 @@ static driver_t bcm_sdhost_driver = {
DRIVER_MODULE(sdhost_bcm, simplebus, bcm_sdhost_driver, bcm_sdhost_devclass,
NULL, NULL);
MODULE_DEPEND(sdhost_bcm, sdhci, 1, 1, 1);
SDHCI_DEPEND(sdhost_bcm);
#ifndef MMCCAM
MMC_DECLARE_BRIDGE(sdhost_bcm);
#endif

View File

@ -465,7 +465,7 @@ static DEFINE_CLASS_0(sdhci, tegra_sdhci_driver, tegra_sdhci_methods,
sizeof(struct tegra_sdhci_softc));
DRIVER_MODULE(sdhci_tegra, simplebus, tegra_sdhci_driver, tegra_sdhci_devclass,
NULL, NULL);
MODULE_DEPEND(sdhci_tegra, sdhci, 1, 1, 1);
SDHCI_DEPEND(sdhci_tegra);
#ifndef MMCCAM
MMC_DECLARE_BRIDGE(sdhci);
#endif

View File

@ -755,7 +755,7 @@ static driver_t ti_sdhci_driver = {
DRIVER_MODULE(sdhci_ti, simplebus, ti_sdhci_driver, ti_sdhci_devclass, NULL,
NULL);
MODULE_DEPEND(sdhci_ti, sdhci, 1, 1, 1);
SDHCI_DEPEND(sdhci_ti);
#ifndef MMCCAM
MMC_DECLARE_BRIDGE(sdhci_ti);

View File

@ -1005,7 +1005,7 @@ static driver_t fsl_sdhci_driver = {
DRIVER_MODULE(sdhci_fsl, simplebus, fsl_sdhci_driver, fsl_sdhci_devclass,
NULL, NULL);
MODULE_DEPEND(sdhci_fsl, sdhci, 1, 1, 1);
SDHCI_DEPEND(sdhci_fsl);
#ifndef MMCCAM
MMC_DECLARE_BRIDGE(sdhci_fsl);

View File

@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/kobj.h>
#include <sys/libkern.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/module.h>
@ -108,19 +109,20 @@ static void sdhci_retune(void *arg);
static void sdhci_set_clock(struct sdhci_slot *slot, uint32_t clock);
static void sdhci_set_power(struct sdhci_slot *slot, u_char power);
static void sdhci_set_transfer_mode(struct sdhci_slot *slot,
struct mmc_data *data);
const struct mmc_data *data);
static void sdhci_start(struct sdhci_slot *slot);
static void sdhci_timeout(void *arg);
static void sdhci_start_command(struct sdhci_slot *slot,
struct mmc_command *cmd);
static void sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data);
static void sdhci_start_data(struct sdhci_slot *slot,
const struct mmc_data *data);
static void sdhci_write_block_pio(struct sdhci_slot *slot);
static void sdhci_transfer_pio(struct sdhci_slot *slot);
#ifdef MMCCAM
/* CAM-related */
static void sdhci_cam_action(struct cam_sim *sim, union ccb *ccb);
static int sdhci_cam_get_possible_host_clock(struct sdhci_slot *slot,
static int sdhci_cam_get_possible_host_clock(const struct sdhci_slot *slot,
int proposed_clock);
static void sdhci_cam_handle_mmcio(struct cam_sim *sim, union ccb *ccb);
static void sdhci_cam_poll(struct cam_sim *sim);
@ -130,12 +132,14 @@ static int sdhci_cam_update_ios(struct sdhci_slot *slot);
#endif
/* helper routines */
static int sdhci_dma_alloc(struct sdhci_slot *slot);
static void sdhci_dma_free(struct sdhci_slot *slot);
static void sdhci_dumpregs(struct sdhci_slot *slot);
static void sdhci_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs,
int error);
static int slot_printf(struct sdhci_slot *slot, const char * fmt, ...)
static int slot_printf(const struct sdhci_slot *slot, const char * fmt, ...)
__printflike(2, 3);
static uint32_t sdhci_tuning_intmask(struct sdhci_slot *slot);
static uint32_t sdhci_tuning_intmask(const struct sdhci_slot *slot);
#define SDHCI_LOCK(_slot) mtx_lock(&(_slot)->mtx)
#define SDHCI_UNLOCK(_slot) mtx_unlock(&(_slot)->mtx)
@ -179,7 +183,7 @@ sdhci_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
}
static int
slot_printf(struct sdhci_slot *slot, const char * fmt, ...)
slot_printf(const struct sdhci_slot *slot, const char * fmt, ...)
{
va_list ap;
int retval;
@ -290,7 +294,7 @@ sdhci_reset(struct sdhci_slot *slot, uint8_t mask)
}
static uint32_t
sdhci_tuning_intmask(struct sdhci_slot *slot)
sdhci_tuning_intmask(const struct sdhci_slot *slot)
{
uint32_t intmask;
@ -737,6 +741,81 @@ sdhci_card_poll(void *arg)
sdhci_card_poll, slot);
}
static int
sdhci_dma_alloc(struct sdhci_slot *slot)
{
int err;
if (!(slot->quirks & SDHCI_QUIRK_BROKEN_SDMA_BOUNDARY)) {
if (MAXPHYS <= 1024 * 4)
slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_4K;
else if (MAXPHYS <= 1024 * 8)
slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_8K;
else if (MAXPHYS <= 1024 * 16)
slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_16K;
else if (MAXPHYS <= 1024 * 32)
slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_32K;
else if (MAXPHYS <= 1024 * 64)
slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_64K;
else if (MAXPHYS <= 1024 * 128)
slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_128K;
else if (MAXPHYS <= 1024 * 256)
slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_256K;
else
slot->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_512K;
}
slot->sdma_bbufsz = SDHCI_SDMA_BNDRY_TO_BBUFSZ(slot->sdma_boundary);
/*
* Allocate the DMA tag for an SDMA bounce buffer.
* Note that the SDHCI specification doesn't state any alignment
* constraint for the SDMA system address. However, controllers
* typically ignore the SDMA boundary bits in SDHCI_DMA_ADDRESS when
* forming the actual address of data, requiring the SDMA buffer to
* be aligned to the SDMA boundary.
*/
err = bus_dma_tag_create(bus_get_dma_tag(slot->bus), slot->sdma_bbufsz,
0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
slot->sdma_bbufsz, 1, slot->sdma_bbufsz, BUS_DMA_ALLOCNOW,
NULL, NULL, &slot->dmatag);
if (err != 0) {
slot_printf(slot, "Can't create DMA tag for SDMA\n");
return (err);
}
/* Allocate DMA memory for the SDMA bounce buffer. */
err = bus_dmamem_alloc(slot->dmatag, (void **)&slot->dmamem,
BUS_DMA_NOWAIT, &slot->dmamap);
if (err != 0) {
slot_printf(slot, "Can't alloc DMA memory for SDMA\n");
bus_dma_tag_destroy(slot->dmatag);
return (err);
}
/* Map the memory of the SDMA bounce buffer. */
err = bus_dmamap_load(slot->dmatag, slot->dmamap,
(void *)slot->dmamem, slot->sdma_bbufsz, sdhci_getaddr,
&slot->paddr, 0);
if (err != 0 || slot->paddr == 0) {
slot_printf(slot, "Can't load DMA memory for SDMA\n");
bus_dmamem_free(slot->dmatag, slot->dmamem, slot->dmamap);
bus_dma_tag_destroy(slot->dmatag);
if (err)
return (err);
else
return (EFAULT);
}
return (0);
}
static void
sdhci_dma_free(struct sdhci_slot *slot)
{
bus_dmamap_unload(slot->dmatag, slot->dmamap);
bus_dmamem_free(slot->dmatag, slot->dmamem, slot->dmamap);
bus_dma_tag_destroy(slot->dmatag);
}
int
sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num)
{
@ -750,42 +829,6 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num)
slot->num = num;
slot->bus = dev;
/* Allocate DMA tag. */
err = bus_dma_tag_create(bus_get_dma_tag(dev),
DMA_BLOCK_SIZE, 0, BUS_SPACE_MAXADDR_32BIT,
BUS_SPACE_MAXADDR, NULL, NULL,
DMA_BLOCK_SIZE, 1, DMA_BLOCK_SIZE,
BUS_DMA_ALLOCNOW, NULL, NULL,
&slot->dmatag);
if (err != 0) {
device_printf(dev, "Can't create DMA tag\n");
SDHCI_LOCK_DESTROY(slot);
return (err);
}
/* Allocate DMA memory. */
err = bus_dmamem_alloc(slot->dmatag, (void **)&slot->dmamem,
BUS_DMA_NOWAIT, &slot->dmamap);
if (err != 0) {
device_printf(dev, "Can't alloc DMA memory\n");
bus_dma_tag_destroy(slot->dmatag);
SDHCI_LOCK_DESTROY(slot);
return (err);
}
/* Map the memory. */
err = bus_dmamap_load(slot->dmatag, slot->dmamap,
(void *)slot->dmamem, DMA_BLOCK_SIZE,
sdhci_getaddr, &slot->paddr, 0);
if (err != 0 || slot->paddr == 0) {
device_printf(dev, "Can't load DMA memory\n");
bus_dmamem_free(slot->dmatag, slot->dmamem, slot->dmamap);
bus_dma_tag_destroy(slot->dmatag);
SDHCI_LOCK_DESTROY(slot);
if (err)
return (err);
else
return (EFAULT);
}
slot->version = (RD2(slot, SDHCI_HOST_VERSION)
>> SDHCI_SPEC_VER_SHIFT) & SDHCI_SPEC_VER_MASK;
if (slot->quirks & SDHCI_QUIRK_MISSING_CAPS) {
@ -801,12 +844,8 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num)
if (slot->version >= SDHCI_SPEC_300) {
if ((caps & SDHCI_SLOTTYPE_MASK) != SDHCI_SLOTTYPE_REMOVABLE &&
(caps & SDHCI_SLOTTYPE_MASK) != SDHCI_SLOTTYPE_EMBEDDED) {
device_printf(dev,
slot_printf(slot,
"Driver doesn't support shared bus slots\n");
bus_dmamap_unload(slot->dmatag, slot->dmamap);
bus_dmamem_free(slot->dmatag, slot->dmamem,
slot->dmamap);
bus_dma_tag_destroy(slot->dmatag);
SDHCI_LOCK_DESTROY(slot);
return (ENXIO);
} else if ((caps & SDHCI_SLOTTYPE_MASK) ==
@ -830,7 +869,7 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num)
*/
if (slot->max_clk == 0) {
slot->max_clk = SDHCI_DEFAULT_MAX_FREQ * 1000000;
device_printf(dev, "Hardware doesn't specify base clock "
slot_printf(slot, "Hardware doesn't specify base clock "
"frequency, using %dMHz as default.\n",
SDHCI_DEFAULT_MAX_FREQ);
}
@ -851,7 +890,7 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num)
* max timeout, but still mention it.
*/
if (slot->timeout_clk == 0) {
device_printf(dev, "Hardware doesn't specify timeout clock "
slot_printf(slot, "Hardware doesn't specify timeout clock "
"frequency, setting BROKEN_TIMEOUT quirk.\n");
slot->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
}
@ -867,7 +906,7 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num)
if ((caps & SDHCI_CAN_VDD_180) && (slot->opt & SDHCI_SLOT_EMBEDDED))
slot->host.host_ocr |= MMC_OCR_LOW_VOLTAGE;
if (slot->host.host_ocr == 0) {
device_printf(dev, "Hardware doesn't report any "
slot_printf(slot, "Hardware doesn't report any "
"support voltages.\n");
}
@ -953,7 +992,7 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num)
slot->retune_count = (caps2 & SDHCI_RETUNE_CNT_MASK) >>
SDHCI_RETUNE_CNT_SHIFT;
if (slot->retune_count > 0xb) {
device_printf(dev, "Unknown re-tuning count "
slot_printf(slot, "Unknown re-tuning count "
"%x, using 1 sec\n", slot->retune_count);
slot->retune_count = 1;
} else if (slot->retune_count != 0)
@ -1012,6 +1051,19 @@ sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num)
if (slot->opt & SDHCI_PLATFORM_TRANSFER)
slot->opt &= ~SDHCI_HAVE_DMA;
if (slot->opt & SDHCI_HAVE_DMA) {
err = sdhci_dma_alloc(slot);
if (err != 0) {
if (slot->opt & SDHCI_TUNING_SUPPORTED) {
free(slot->tune_req, M_DEVBUF);
free(slot->tune_cmd, M_DEVBUF);
free(slot->tune_data, M_DEVBUF);
}
SDHCI_LOCK_DESTROY(slot);
return (err);
}
}
if (bootverbose || sdhci_debug) {
slot_printf(slot,
"%uMHz%s %s VDD:%s%s%s VCCQ: 3.3V%s%s DRV: B%s%s%s %s %s\n",
@ -1109,9 +1161,8 @@ sdhci_cleanup_slot(struct sdhci_slot *slot)
SDHCI_LOCK(slot);
sdhci_reset(slot, SDHCI_RESET_ALL);
SDHCI_UNLOCK(slot);
bus_dmamap_unload(slot->dmatag, slot->dmamap);
bus_dmamem_free(slot->dmatag, slot->dmamem, slot->dmamap);
bus_dma_tag_destroy(slot->dmatag);
if (slot->opt & SDHCI_HAVE_DMA)
sdhci_dma_free(slot);
if (slot->opt & SDHCI_TUNING_SUPPORTED) {
free(slot->tune_req, M_DEVBUF);
free(slot->tune_cmd, M_DEVBUF);
@ -1175,7 +1226,7 @@ sdhci_generic_get_card_present(device_t brdev __unused, struct sdhci_slot *slot)
void
sdhci_generic_set_uhs_timing(device_t brdev __unused, struct sdhci_slot *slot)
{
struct mmc_ios *ios;
const struct mmc_ios *ios;
uint16_t hostctrl2;
if (slot->version < SDHCI_SPEC_300)
@ -1308,7 +1359,7 @@ int
sdhci_generic_tune(device_t brdev __unused, device_t reqdev, bool hs400)
{
struct sdhci_slot *slot = device_get_ivars(reqdev);
struct mmc_ios *ios = &slot->host.ios;
const struct mmc_ios *ios = &slot->host.ios;
struct mmc_command *tune_cmd;
struct mmc_data *tune_data;
uint32_t opcode;
@ -1564,7 +1615,7 @@ sdhci_timeout(void *arg)
}
static void
sdhci_set_transfer_mode(struct sdhci_slot *slot, struct mmc_data *data)
sdhci_set_transfer_mode(struct sdhci_slot *slot, const struct mmc_data *data)
{
uint16_t mode;
@ -1766,9 +1817,9 @@ sdhci_finish_command(struct sdhci_slot *slot)
}
static void
sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data)
sdhci_start_data(struct sdhci_slot *slot, const struct mmc_data *data)
{
uint32_t target_timeout, current_timeout;
uint32_t blkcnt, blksz, current_timeout, sdma_bbufsz, target_timeout;
uint8_t div;
if (data == NULL && (slot->curcmd->flags & MMC_RSP_BUSY) == 0) {
@ -1804,7 +1855,7 @@ sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data)
/* Use DMA if possible. */
if ((slot->opt & SDHCI_HAVE_DMA))
slot->flags |= SDHCI_USE_DMA;
/* If data is small, broken DMA may return zeroes instead of data, */
/* If data is small, broken DMA may return zeroes instead of data. */
if ((slot->quirks & SDHCI_QUIRK_BROKEN_TIMINGS) &&
(data->len <= 512))
slot->flags &= ~SDHCI_USE_DMA;
@ -1814,20 +1865,22 @@ sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data)
slot->flags &= ~SDHCI_USE_DMA;
/* Load DMA buffer. */
if (slot->flags & SDHCI_USE_DMA) {
sdma_bbufsz = slot->sdma_bbufsz;
if (data->flags & MMC_DATA_READ)
bus_dmamap_sync(slot->dmatag, slot->dmamap,
BUS_DMASYNC_PREREAD);
else {
memcpy(slot->dmamem, data->data,
(data->len < DMA_BLOCK_SIZE) ?
data->len : DMA_BLOCK_SIZE);
memcpy(slot->dmamem, data->data, ulmin(data->len,
sdma_bbufsz));
bus_dmamap_sync(slot->dmatag, slot->dmamap,
BUS_DMASYNC_PREWRITE);
}
WR4(slot, SDHCI_DMA_ADDRESS, slot->paddr);
/* Interrupt aggregation: Mask border interrupt
* for the last page and unmask else. */
if (data->len == DMA_BLOCK_SIZE)
/*
* Interrupt aggregation: Mask border interrupt for the last
* bounce buffer and unmask otherwise.
*/
if (data->len == sdma_bbufsz)
slot->intmask &= ~SDHCI_INT_DMA_END;
else
slot->intmask |= SDHCI_INT_DMA_END;
@ -1835,16 +1888,15 @@ sdhci_start_data(struct sdhci_slot *slot, struct mmc_data *data)
}
/* Current data offset for both PIO and DMA. */
slot->offset = 0;
/* Set block size and request IRQ on 4K border. */
WR2(slot, SDHCI_BLOCK_SIZE, SDHCI_MAKE_BLKSZ(DMA_BOUNDARY,
(data->len < 512) ? data->len : 512));
/* Set block size and request border interrupts on the SDMA boundary. */
blksz = SDHCI_MAKE_BLKSZ(slot->sdma_boundary, ulmin(data->len, 512));
WR2(slot, SDHCI_BLOCK_SIZE, blksz);
/* Set block count. */
WR2(slot, SDHCI_BLOCK_COUNT, (data->len + 511) / 512);
blkcnt = howmany(data->len, 512);
WR2(slot, SDHCI_BLOCK_COUNT, blkcnt);
if (__predict_false(sdhci_debug > 1))
slot_printf(slot, "Block size: %02x, count %lu\n",
(unsigned int)SDHCI_MAKE_BLKSZ(DMA_BOUNDARY, (data->len < 512) ? data->len : 512),
(unsigned long)(data->len + 511) / 512);
slot_printf(slot, "Blk size: 0x%08x | Blk cnt: 0x%08x\n",
blksz, blkcnt);
}
void
@ -1868,7 +1920,7 @@ sdhci_finish_data(struct sdhci_slot *slot)
bus_dmamap_sync(slot->dmatag, slot->dmamap,
BUS_DMASYNC_POSTREAD);
memcpy((u_char*)data->data + slot->offset, slot->dmamem,
(left < DMA_BLOCK_SIZE) ? left : DMA_BLOCK_SIZE);
ulmin(left, slot->sdma_bbufsz));
} else
bus_dmamap_sync(slot->dmatag, slot->dmamap,
BUS_DMASYNC_POSTWRITE);
@ -1892,15 +1944,14 @@ sdhci_finish_data(struct sdhci_slot *slot)
static void
sdhci_start(struct sdhci_slot *slot)
{
union ccb *ccb;
union ccb *ccb;
struct ccb_mmcio *mmcio;
ccb = slot->ccb;
if (ccb == NULL)
return;
struct ccb_mmcio *mmcio;
mmcio = &ccb->mmcio;
if (!(slot->flags & CMD_STARTED)) {
slot->flags |= CMD_STARTED;
sdhci_start_command(slot, &mmcio->cmd);
@ -1932,7 +1983,7 @@ sdhci_start(struct sdhci_slot *slot)
static void
sdhci_start(struct sdhci_slot *slot)
{
struct mmc_request *req;
const struct mmc_request *req;
req = slot->req;
if (req == NULL)
@ -2061,6 +2112,7 @@ sdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask)
{
struct mmc_data *data;
size_t left;
uint32_t sdma_bbufsz;
if (!slot->curcmd) {
slot_printf(slot, "Got data interrupt 0x%08x, but "
@ -2115,6 +2167,7 @@ sdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask)
/* Handle DMA border. */
if (intmask & SDHCI_INT_DMA_END) {
data = slot->curcmd->data;
sdma_bbufsz = slot->sdma_bbufsz;
/* Unload DMA buffer ... */
left = data->len - slot->offset;
@ -2122,26 +2175,28 @@ sdhci_data_irq(struct sdhci_slot *slot, uint32_t intmask)
bus_dmamap_sync(slot->dmatag, slot->dmamap,
BUS_DMASYNC_POSTREAD);
memcpy((u_char*)data->data + slot->offset, slot->dmamem,
(left < DMA_BLOCK_SIZE) ? left : DMA_BLOCK_SIZE);
ulmin(left, sdma_bbufsz));
} else {
bus_dmamap_sync(slot->dmatag, slot->dmamap,
BUS_DMASYNC_POSTWRITE);
}
/* ... and reload it again. */
slot->offset += DMA_BLOCK_SIZE;
slot->offset += sdma_bbufsz;
left = data->len - slot->offset;
if (data->flags & MMC_DATA_READ) {
bus_dmamap_sync(slot->dmatag, slot->dmamap,
BUS_DMASYNC_PREREAD);
} else {
memcpy(slot->dmamem, (u_char*)data->data + slot->offset,
(left < DMA_BLOCK_SIZE)? left : DMA_BLOCK_SIZE);
ulmin(left, sdma_bbufsz));
bus_dmamap_sync(slot->dmatag, slot->dmamap,
BUS_DMASYNC_PREWRITE);
}
/* Interrupt aggregation: Mask border interrupt
* for the last page. */
if (left == DMA_BLOCK_SIZE) {
/*
* Interrupt aggregation: Mask border interrupt for the last
* bounce buffer.
*/
if (left == sdma_bbufsz) {
slot->intmask &= ~SDHCI_INT_DMA_END;
WR4(slot, SDHCI_SIGNAL_ENABLE, slot->intmask);
}
@ -2264,7 +2319,7 @@ int
sdhci_generic_read_ivar(device_t bus, device_t child, int which,
uintptr_t *result)
{
struct sdhci_slot *slot = device_get_ivars(child);
const struct sdhci_slot *slot = device_get_ivars(child);
switch (which) {
default:
@ -2427,6 +2482,7 @@ sdhci_generic_write_ivar(device_t bus, device_t child, int which,
void
sdhci_start_slot(struct sdhci_slot *slot)
{
if ((slot->devq = cam_simq_alloc(1)) == NULL) {
goto fail;
}
@ -2586,7 +2642,8 @@ sdhci_cam_poll(struct cam_sim *sim)
}
static int
sdhci_cam_get_possible_host_clock(struct sdhci_slot *slot, int proposed_clock)
sdhci_cam_get_possible_host_clock(const struct sdhci_slot *slot,
int proposed_clock)
{
int max_clock, clock, i;
@ -2613,15 +2670,14 @@ sdhci_cam_get_possible_host_clock(struct sdhci_slot *slot, int proposed_clock)
return clock;
}
int
static int
sdhci_cam_settran_settings(struct sdhci_slot *slot, union ccb *ccb)
{
struct mmc_ios *ios;
struct mmc_ios *new_ios;
struct ccb_trans_settings_mmc *cts;
const struct mmc_ios *new_ios;
const struct ccb_trans_settings_mmc *cts;
ios = &slot->host.ios;
cts = &ccb->cts.proto_specific.mmc;
new_ios = &cts->ios;
@ -2659,7 +2715,7 @@ sdhci_cam_settran_settings(struct sdhci_slot *slot, union ccb *ccb)
return (sdhci_cam_update_ios(slot));
}
int
static int
sdhci_cam_update_ios(struct sdhci_slot *slot)
{
struct mmc_ios *ios = &slot->host.ios;
@ -2701,10 +2757,10 @@ sdhci_cam_update_ios(struct sdhci_slot *slot)
return (0);
}
int
static int
sdhci_cam_request(struct sdhci_slot *slot, union ccb *ccb)
{
struct ccb_mmcio *mmcio;
const struct ccb_mmcio *mmcio;
mmcio = &ccb->mmcio;
@ -2739,4 +2795,4 @@ sdhci_cam_request(struct sdhci_slot *slot, union ccb *ccb)
}
#endif /* MMCCAM */
MODULE_VERSION(sdhci, 1);
MODULE_VERSION(sdhci, SDHCI_VERSION);

View File

@ -32,8 +32,8 @@
#include "opt_mmccam.h"
#define DMA_BLOCK_SIZE 4096
#define DMA_BOUNDARY 0 /* DMA reload every 4K */
/* Macro for sizing the SDMA bounce buffer on the SDMA buffer boundary. */
#define SDHCI_SDMA_BNDRY_TO_BBUFSZ(bndry) (4096 * (1 << bndry))
/* Controller doesn't honor resets unless we touch the clock register */
#define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1 << 0)
@ -95,6 +95,8 @@
#define SDHCI_QUIRK_BROKEN_AUTO_STOP (1 << 28)
/* Controller supports eMMC HS400 mode if SDHCI_CAN_SDR104 is set. */
#define SDHCI_QUIRK_MMC_HS400_IF_CAN_SDR104 (1 << 29)
/* SDMA boundary in SDHCI_BLOCK_SIZE broken - use front-end supplied value. */
#define SDHCI_QUIRK_BROKEN_SDMA_BOUNDARY (1 << 30)
/*
* Controller registers
@ -102,6 +104,14 @@
#define SDHCI_DMA_ADDRESS 0x00
#define SDHCI_BLOCK_SIZE 0x04
#define SDHCI_BLKSZ_SDMA_BNDRY_4K 0x00
#define SDHCI_BLKSZ_SDMA_BNDRY_8K 0x01
#define SDHCI_BLKSZ_SDMA_BNDRY_16K 0x02
#define SDHCI_BLKSZ_SDMA_BNDRY_32K 0x03
#define SDHCI_BLKSZ_SDMA_BNDRY_64K 0x04
#define SDHCI_BLKSZ_SDMA_BNDRY_128K 0x05
#define SDHCI_BLKSZ_SDMA_BNDRY_256K 0x06
#define SDHCI_BLKSZ_SDMA_BNDRY_512K 0x07
#define SDHCI_MAKE_BLKSZ(dma, blksz) (((dma & 0x7) << 12) | (blksz & 0xFFF))
#define SDHCI_BLOCK_COUNT 0x06
@ -362,6 +372,8 @@ struct sdhci_slot {
bus_dmamap_t dmamap;
u_char *dmamem;
bus_addr_t paddr; /* DMA buffer address */
uint32_t sdma_bbufsz; /* SDMA bounce buffer size */
uint8_t sdma_boundary; /* SDMA boundary */
struct task card_task; /* Card presence check task */
struct timeout_task
card_delayed_task;/* Card insert delayed task */
@ -434,4 +446,9 @@ bool sdhci_generic_get_card_present(device_t brdev, struct sdhci_slot *slot);
void sdhci_generic_set_uhs_timing(device_t brdev, struct sdhci_slot *slot);
void sdhci_handle_card_present(struct sdhci_slot *slot, bool is_present);
#define SDHCI_VERSION 2
#define SDHCI_DEPEND(name) \
MODULE_DEPEND(name, sdhci, SDHCI_VERSION, SDHCI_VERSION, SDHCI_VERSION);
#endif /* __SDHCI_H__ */

View File

@ -457,7 +457,7 @@ static devclass_t sdhci_acpi_devclass;
DRIVER_MODULE(sdhci_acpi, acpi, sdhci_acpi_driver, sdhci_acpi_devclass, NULL,
NULL);
MODULE_DEPEND(sdhci_acpi, sdhci, 1, 1, 1);
SDHCI_DEPEND(sdhci_acpi);
#ifndef MMCCAM
MMC_DECLARE_BRIDGE(sdhci_acpi);

View File

@ -80,6 +80,7 @@ struct sdhci_fdt_softc {
u_int quirks; /* Chip specific quirks */
u_int caps; /* If we override SDHCI_CAPABILITIES */
uint32_t max_clk; /* Max possible freq */
uint8_t sdma_boundary; /* If we override the SDMA boundary */
struct resource *irq_res; /* IRQ resource */
void *intrhand; /* Interrupt handle */
@ -206,7 +207,9 @@ sdhci_fdt_probe(device_t dev)
device_set_desc(dev, "generic fdt SDHCI controller");
break;
case SDHCI_FDT_QUALCOMM:
sc->quirks = SDHCI_QUIRK_ALL_SLOTS_NON_REMOVABLE;
sc->quirks = SDHCI_QUIRK_ALL_SLOTS_NON_REMOVABLE |
SDHCI_QUIRK_BROKEN_SDMA_BOUNDARY;
sc->sdma_boundary = SDHCI_BLKSZ_SDMA_BNDRY_4K;
device_set_desc(dev, "Qualcomm FDT SDHCI controller");
break;
case SDHCI_FDT_XLNX_ZY7:
@ -271,6 +274,7 @@ sdhci_fdt_attach(device_t dev)
slot->quirks = sc->quirks;
slot->caps = sc->caps;
slot->max_clk = sc->max_clk;
slot->sdma_boundary = sc->sdma_boundary;
if (sdhci_init_slot(dev, slot, i) != 0)
continue;
@ -353,7 +357,7 @@ static devclass_t sdhci_fdt_devclass;
DRIVER_MODULE(sdhci_fdt, simplebus, sdhci_fdt_driver, sdhci_fdt_devclass,
NULL, NULL);
MODULE_DEPEND(sdhci_fdt, sdhci, 1, 1, 1);
SDHCI_DEPEND(sdhci_fdt);
#ifndef MMCCAM
MMC_DECLARE_BRIDGE(sdhci_fdt);
#endif

View File

@ -526,7 +526,7 @@ static devclass_t sdhci_pci_devclass;
DRIVER_MODULE(sdhci_pci, pci, sdhci_pci_driver, sdhci_pci_devclass, NULL,
NULL);
MODULE_DEPEND(sdhci_pci, sdhci, 1, 1, 1);
SDHCI_DEPEND(sdhci_pci);
#ifndef MMCCAM
MMC_DECLARE_BRIDGE(sdhci_pci);

View File

@ -550,7 +550,7 @@ static devclass_t sdhci_xenon_devclass;
DRIVER_MODULE(sdhci_xenon, simplebus, sdhci_xenon_driver, sdhci_xenon_devclass,
NULL, NULL);
MODULE_DEPEND(sdhci_xenon, sdhci, 1, 1, 1);
SDHCI_DEPEND(sdhci_xenon);
#ifndef MMCCAM
MMC_DECLARE_BRIDGE(sdhci_xenon);
#endif