MMC: added alternative MMC driver

mmc: Disable CMD23 transfers on all cards

Pending wire-level investigation of these types of transfers
and associated errors on bcm2835-mmc, disable for now. Fallback of
CMD18/CMD25 transfers will be used automatically by the MMC layer.

Reported/Tested-by: Gellert Weisz <gellert@raspberrypi.org>

mmc: bcm2835-mmc: enable DT support for all architectures

Both ARCH_BCM2835 and ARCH_BCM270x are built with OF now.
Enable Device Tree support for all architectures.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>

mmc: bcm2835-mmc: fix probe error handling

Probe error handling is broken in several places.
Simplify error handling by using device managed functions.
Replace pr_{err,info} with dev_{err,info}.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>

bcm2835-mmc: Add locks when accessing sdhost registers

bcm2835-mmc: Add range of debug options for slowing things down

bcm2835-mmc: Add option to disable some delays

bcm2835-mmc: Add option to disable MMC_QUIRK_BLK_NO_CMD23

bcm2835-mmc: Default to disabling MMC_QUIRK_BLK_NO_CMD23

bcm2835-mmc: Adding overclocking option

Allow a different clock speed to be substitued for a requested 50MHz.
This option is exposed using the "overclock_50" DT parameter.
Note that the mmc interface is restricted to EVEN integer divisions of
250MHz, and the highest sensible option is 63 (250/4 = 62.5), the
next being 125 (250/2) which is much too high.

Use at your own risk.

bcm2835-mmc: Round up the overclock, so 62 works for 62.5Mhz

Also only warn once for each overclock setting.

mmc: bcm2835-mmc: Make available on ARCH_BCM2835

Make the bcm2835-mmc driver available for use on ARCH_BCM2835.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>

BCM270x_DT: add bcm2835-mmc entry

Add Device Tree entry for bcm2835-mmc.
In non-DT mode, don't add the device in the board file.

Signed-off-by: Noralf Trønnes <noralf@tronnes.org>

bcm2835-mmc: Don't overwrite MMC capabilities from DT

bcm2835-mmc: Don't override bus width capabilities from devicetree

Take out the force setting of the MMC_CAP_4_BIT_DATA host capability
so that the result read from devicetree via mmc_of_parse() is
preserved.

bcm2835-mmc: Only claim one DMA channel

With both MMC controllers enabled there are few DMA channels left. The
bcm2835-mmc driver only uses DMA in one direction at a time, so it
doesn't need to claim two channels.

See: https://github.com/raspberrypi/linux/issues/1327

Signed-off-by: Phil Elwell <phil@raspberrypi.org>

bcm2835-mmc: New timer API

mmc: bcm2835-mmc: Support underclocking

Support underclocking of the SD bus using the max-frequency DT property
(which currently has no DT parameter). The sd_overclock parameter
already provides another way to achieve the same thing which should be
equivalent in end result, but it is a bug not to support max-frequency
as well.

See: https://github.com/raspberrypi/linux/issues/2350

Signed-off-by: Phil Elwell <phil@raspberrypi.org>

mmc/bcm2835: Recover from MMC_SEND_EXT_CSD

If the user issues an "mmc extcsd read", the SD controller receives
what it thinks is a SEND_IF_COND command with an unexpected data block.
The resulting operations leave the FSM stuck in READWAIT, a state which
persists until the MMC framework resets the controller, by which point
the root filesystem is likely to have been unmounted.

A less heavyweight solution is to detect the condition and nudge the
FSM by asserting the (self-clearing) FORCE_DATA_MODE bit.

N.B. This workaround was essentially discovered by accident and without
a full understanding the inner workings of the controller, so it is
fortunate that the "fix" only modifies error paths.

See: https://github.com/raspberrypi/linux/issues/2728

Signed-off-by: Phil Elwell <phil@raspberrypi.org>

bcm2835-mmc: Fix DMA channel leak

The BCM2835 MMC host driver requests a DMA channel on probe but neglects
to release the channel in the probe error path and on driver unbind.

I'm seeing this happen on every boot of the Compute Module 3: On first
driver probe, DMA channel 2 is allocated and then leaked with a "could
not get clk, deferring probe" message. On second driver probe, channel 4
is allocated.

Fix it.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
Cc: Frank Pavlic <f.pavlic@kunbus.de>

bcm2835-mmc: Fix struct mmc_host leak on probe

The BCM2835 MMC host driver requests the bus address of the host's
register map on probe.  If that fails, the driver leaks the struct
mmc_host allocated earlier.

Fix it.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
Cc: Frank Pavlic <f.pavlic@kunbus.de>

bcm2835-mmc: Fix duplicate free_irq() on remove

The BCM2835 MMC host driver requests its interrupt as a device-managed
resource, so the interrupt is automatically freed after the driver is
unbound.

However on driver unbind, bcm2835_mmc_remove() frees the interrupt
explicitly to avoid invocation of the interrupt handler after driver
structures have been torn down.

The interrupt is thus freed twice, leading to a WARN splat in
__free_irq().  Fix by not requesting the interrupt as a device-managed
resource.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
Cc: Frank Pavlic <f.pavlic@kunbus.de>

bcm2835-mmc: Handle mmc_add_host() errors

The BCM2835 MMC host driver calls mmc_add_host() but doesn't check its
return value.  Errors occurring in that function are therefore not
handled.  Fix it.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
Cc: Frank Pavlic <f.pavlic@kunbus.de>

bcm2835-mmc: Deduplicate reset of driver data on remove

The BCM2835 MMC host driver sets the device's driver data pointer to
NULL on ->remove() even though the driver core subsequently does the
same in __device_release_driver().  Drop the duplicate assignment.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
Cc: Frank Pavlic <f.pavlic@kunbus.de>
This commit is contained in:
gellert
2014-08-15 16:35:06 +01:00
committed by popcornmix
parent 255fa6122b
commit 7edfa87d10
8 changed files with 1668 additions and 5 deletions

View File

@@ -166,6 +166,13 @@ static DEFINE_MUTEX(open_lock);
module_param(perdev_minors, int, 0444);
MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device");
/*
* Allow quirks to be overridden for the current card
*/
static char *card_quirks;
module_param(card_quirks, charp, 0644);
MODULE_PARM_DESC(card_quirks, "Force the use of the indicated quirks (a bitfield)");
static inline int mmc_blk_part_switch(struct mmc_card *card,
unsigned int part_type);
@@ -2904,6 +2911,7 @@ static int mmc_blk_probe(struct mmc_card *card)
{
struct mmc_blk_data *md, *part_md;
char cap_str[10];
char quirk_str[24];
/*
* Check that the card supports the command class(es) we need.
@@ -2911,7 +2919,16 @@ static int mmc_blk_probe(struct mmc_card *card)
if (!(card->csd.cmdclass & CCC_BLOCK_READ))
return -ENODEV;
mmc_fixup_device(card, mmc_blk_fixups);
if (card_quirks) {
unsigned long quirks;
if (kstrtoul(card_quirks, 0, &quirks) == 0)
card->quirks = (unsigned int)quirks;
else
pr_err("mmc_block: Invalid card_quirks parameter '%s'\n",
card_quirks);
}
else
mmc_fixup_device(card, mmc_blk_fixups);
card->complete_wq = alloc_workqueue("mmc_complete",
WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
@@ -2926,9 +2943,14 @@ static int mmc_blk_probe(struct mmc_card *card)
string_get_size((u64)get_capacity(md->disk), 512, STRING_UNITS_2,
cap_str, sizeof(cap_str));
pr_info("%s: %s %s %s %s\n",
if (card->quirks)
snprintf(quirk_str, sizeof(quirk_str),
" (quirks 0x%08x)", card->quirks);
else
quirk_str[0] = '\0';
pr_info("%s: %s %s %s%s%s\n",
md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
cap_str, md->read_only ? "(ro)" : "");
cap_str, md->read_only ? " (ro)" : "", quirk_str);
if (mmc_blk_alloc_parts(card, md))
goto out;

View File

@@ -1920,7 +1920,8 @@ EXPORT_SYMBOL(mmc_erase);
int mmc_can_erase(struct mmc_card *card)
{
if ((card->host->caps & MMC_CAP_ERASE) &&
(card->csd.cmdclass & CCC_ERASE) && card->erase_size)
(card->csd.cmdclass & CCC_ERASE) && card->erase_size &&
!(card->quirks & MMC_QUIRK_ERASE_BROKEN))
return 1;
return 0;
}

View File

@@ -400,15 +400,30 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
{
int err;
struct mmc_host *host;
int id;
host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
if (!host)
return NULL;
/* If OF aliases exist, start dynamic assignment after highest */
id = of_alias_get_highest_id("mmc");
id = (id < 0) ? 0 : id + 1;
/* If this devices has OF node, maybe it has an alias */
if (dev->of_node) {
int of_id = of_alias_get_id(dev->of_node, "mmc");
if (of_id < 0)
dev_warn(dev, "/aliases ID not available\n");
else
id = of_id;
}
/* scanning will be enabled when we're ready */
host->rescan_disable = 1;
err = ida_simple_get(&mmc_host_ida, 0, 0, GFP_KERNEL);
err = ida_simple_get(&mmc_host_ida, id, 0, GFP_KERNEL);
if (err < 0) {
kfree(host);
return NULL;

View File

@@ -99,6 +99,14 @@ static const struct mmc_fixup mmc_blk_fixups[] = {
MMC_FIXUP("V10016", CID_MANFID_KINGSTON, CID_OEMID_ANY, add_quirk_mmc,
MMC_QUIRK_TRIM_BROKEN),
/*
* On some Kingston SD cards, multiple erases of less than 64
* sectors can cause corruption.
*/
MMC_FIXUP("SD16G", 0x41, 0x3432, add_quirk, MMC_QUIRK_ERASE_BROKEN),
MMC_FIXUP("SD32G", 0x41, 0x3432, add_quirk, MMC_QUIRK_ERASE_BROKEN),
MMC_FIXUP("SD64G", 0x41, 0x3432, add_quirk, MMC_QUIRK_ERASE_BROKEN),
END_FIXUP
};

View File

@@ -5,6 +5,35 @@
comment "MMC/SD/SDIO Host Controller Drivers"
config MMC_BCM2835_MMC
tristate "MMC support on BCM2835"
depends on MACH_BCM2708 || MACH_BCM2709 || ARCH_BCM2835
help
This selects the MMC Interface on BCM2835.
If you have a controller with this interface, say Y or M here.
If unsure, say N.
config MMC_BCM2835_DMA
bool "DMA support on BCM2835 Arasan controller"
depends on MMC_BCM2835_MMC
help
Enable DMA support on the Arasan SDHCI controller in Broadcom 2708
based chips.
If unsure, say N.
config MMC_BCM2835_PIO_DMA_BARRIER
int "Block count limit for PIO transfers"
depends on MMC_BCM2835_MMC && MMC_BCM2835_DMA
range 0 256
default 2
help
The inclusive limit in bytes under which PIO will be used instead of DMA
If unsure, say 2 here.
config MMC_DEBUG
bool "MMC host drivers debugging"
depends on MMC != n

View File

@@ -23,6 +23,7 @@ obj-$(CONFIG_MMC_SDHCI_SIRF) += sdhci-sirf.o
obj-$(CONFIG_MMC_SDHCI_F_SDH30) += sdhci_f_sdh30.o
obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o
obj-$(CONFIG_MMC_SDHCI_AM654) += sdhci_am654.o
obj-$(CONFIG_MMC_BCM2835_MMC) += bcm2835-mmc.o
obj-$(CONFIG_MMC_WBSD) += wbsd.o
obj-$(CONFIG_MMC_AU1X) += au1xmmc.o
obj-$(CONFIG_MMC_ALCOR) += alcor.o

File diff suppressed because it is too large Load Diff

View File

@@ -270,6 +270,8 @@ struct mmc_card {
#define MMC_QUIRK_TRIM_BROKEN (1<<12) /* Skip trim */
#define MMC_QUIRK_BROKEN_HPI (1<<13) /* Disable broken HPI support */
#define MMC_QUIRK_ERASE_BROKEN (1<<31) /* Skip erase */
bool reenable_cmdq; /* Re-enable Command Queue */
unsigned int erase_size; /* erase size in sectors */