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> bcm2835_mmc: Remove vestigial threaded IRQ With SDIO processing now managed by the MMC framework with a workqueue, the bcm2835_mmc driver no longer needs a threaded IRQ. Signed-off-by: Phil Elwell <phil@raspberrypi.org> Add missing dma_unmap_sg calls to free relevant swiotlb bounce buffers. This prevents DMA leaks. Signed-off-by: Yaroslav Rosomakho <yaroslavros@gmail.com> Limit max_req_size under arm64 (or any other platform that uses swiotlb) to prevent potential buffer overflow due to bouncing. Signed-off-by: Yaroslav Rosomakho <yaroslavros@gmail.com> mmc: sdhci: Silence MMC warnings When the MMC isn't plugged in, the driver will spam the console which is pretty annoying when using NFS. Signed-off-by: Maxime Ripard <maxime@cerno.tech> mmc: sdhci-iproc: Fix vmmc regulators on iProc The Linux support for controlling card power via regulators appears to be contentious. I would argue that the default behaviour is contrary to the SDHCI spec - turning off the power writes a reserved value to the SD Bus Voltage Select field of the Power Control Register, which seems to kill the Arasan/iProc controller - but fortunately there is a hook in sdhci_ops to override the behaviour. Borrow the implementation from sdhci_arasan_set_power. Signed-off-by: Phil Elwell <phil@raspberrypi.org> bcm2835-mmc: uninitialized_var is no more
This commit is contained in:
@@ -171,6 +171,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);
|
||||
static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
|
||||
@@ -2886,6 +2893,8 @@ static int mmc_blk_probe(struct mmc_card *card)
|
||||
{
|
||||
struct mmc_blk_data *md;
|
||||
int ret = 0;
|
||||
char quirk_str[24];
|
||||
char cap_str[10];
|
||||
|
||||
/*
|
||||
* Check that the card supports the command class(es) we need.
|
||||
@@ -2893,6 +2902,15 @@ static int mmc_blk_probe(struct mmc_card *card)
|
||||
if (!(card->csd.cmdclass & CCC_BLOCK_READ))
|
||||
return -ENODEV;
|
||||
|
||||
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",
|
||||
@@ -2908,6 +2926,17 @@ static int mmc_blk_probe(struct mmc_card *card)
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
string_get_size((u64)get_capacity(md->disk), 512, STRING_UNITS_2,
|
||||
cap_str, sizeof(cap_str));
|
||||
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)" : "", quirk_str);
|
||||
|
||||
ret = mmc_blk_alloc_parts(card, md);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -1801,7 +1801,8 @@ EXPORT_SYMBOL(mmc_erase);
|
||||
|
||||
int mmc_can_erase(struct mmc_card *card)
|
||||
{
|
||||
if (card->csd.cmdclass & CCC_ERASE && card->erase_size)
|
||||
if (card->csd.cmdclass & CCC_ERASE && card->erase_size &&
|
||||
!(card->quirks & MMC_QUIRK_ERASE_BROKEN))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -99,6 +99,14 @@ static const struct mmc_fixup __maybe_unused 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
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -23,6 +23,7 @@ obj-$(CONFIG_MMC_SDHCI_F_SDH30) += sdhci_f_sdh30.o
|
||||
obj-$(CONFIG_MMC_SDHCI_MILBEAUT) += sdhci-milbeaut.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
|
||||
|
||||
1576
drivers/mmc/host/bcm2835-mmc.c
Normal file
1576
drivers/mmc/host/bcm2835-mmc.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -173,6 +173,17 @@ static unsigned int sdhci_iproc_get_max_clock(struct sdhci_host *host)
|
||||
return pltfm_host->clock;
|
||||
}
|
||||
|
||||
static void sdhci_iproc_set_power(struct sdhci_host *host, unsigned char mode,
|
||||
unsigned short vdd)
|
||||
{
|
||||
if (!IS_ERR(host->mmc->supply.vmmc)) {
|
||||
struct mmc_host *mmc = host->mmc;
|
||||
|
||||
mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
|
||||
}
|
||||
sdhci_set_power_noreg(host, mode, vdd);
|
||||
}
|
||||
|
||||
/*
|
||||
* There is a known bug on BCM2711's SDHCI core integration where the
|
||||
* controller will hang when the difference between the core clock and the bus
|
||||
@@ -207,6 +218,7 @@ static const struct sdhci_ops sdhci_iproc_32only_ops = {
|
||||
.write_b = sdhci_iproc_writeb,
|
||||
.set_clock = sdhci_set_clock,
|
||||
.get_max_clock = sdhci_iproc_get_max_clock,
|
||||
.set_power = sdhci_iproc_set_power,
|
||||
.set_bus_width = sdhci_set_bus_width,
|
||||
.reset = sdhci_reset,
|
||||
.set_uhs_signaling = sdhci_set_uhs_signaling,
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
pr_debug("%s: " DRIVER_NAME ": " f, mmc_hostname(host->mmc), ## x)
|
||||
|
||||
#define SDHCI_DUMP(f, x...) \
|
||||
pr_err("%s: " DRIVER_NAME ": " f, mmc_hostname(host->mmc), ## x)
|
||||
pr_debug("%s: " DRIVER_NAME ": " f, mmc_hostname(host->mmc), ## x)
|
||||
|
||||
#define MAX_TUNING_LOOP 40
|
||||
|
||||
@@ -3143,7 +3143,7 @@ static void sdhci_timeout_timer(struct timer_list *t)
|
||||
spin_lock_irqsave(&host->lock, flags);
|
||||
|
||||
if (host->cmd && !sdhci_data_line_cmd(host->cmd)) {
|
||||
pr_err("%s: Timeout waiting for hardware cmd interrupt.\n",
|
||||
pr_debug("%s: Timeout waiting for hardware cmd interrupt.\n",
|
||||
mmc_hostname(host->mmc));
|
||||
sdhci_dumpregs(host);
|
||||
|
||||
@@ -3165,7 +3165,7 @@ static void sdhci_timeout_data_timer(struct timer_list *t)
|
||||
|
||||
if (host->data || host->data_cmd ||
|
||||
(host->cmd && sdhci_data_line_cmd(host->cmd))) {
|
||||
pr_err("%s: Timeout waiting for hardware interrupt.\n",
|
||||
pr_debug("%s: Timeout waiting for hardware interrupt.\n",
|
||||
mmc_hostname(host->mmc));
|
||||
sdhci_dumpregs(host);
|
||||
|
||||
|
||||
@@ -293,6 +293,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 */
|
||||
|
||||
Reference in New Issue
Block a user