diff options
Diffstat (limited to 'drivers/mmc')
| -rw-r--r-- | drivers/mmc/core/block.c | 92 | ||||
| -rw-r--r-- | drivers/mmc/core/bus.c | 2 | ||||
| -rw-r--r-- | drivers/mmc/core/card.h | 7 | ||||
| -rw-r--r-- | drivers/mmc/core/core.c | 20 | ||||
| -rw-r--r-- | drivers/mmc/core/host.c | 11 | ||||
| -rw-r--r-- | drivers/mmc/core/mmc.c | 6 | ||||
| -rw-r--r-- | drivers/mmc/core/queue.c | 9 | ||||
| -rw-r--r-- | drivers/mmc/core/queue.h | 1 | ||||
| -rw-r--r-- | drivers/mmc/core/quirks.h | 116 | ||||
| -rw-r--r-- | drivers/mmc/core/sd.c | 213 | ||||
| -rw-r--r-- | drivers/mmc/core/sd_ops.c | 134 | ||||
| -rw-r--r-- | drivers/mmc/core/sd_ops.h | 6 | ||||
| -rw-r--r-- | drivers/mmc/host/Kconfig | 30 | ||||
| -rw-r--r-- | drivers/mmc/host/Makefile | 1 | ||||
| -rw-r--r-- | drivers/mmc/host/bcm2835-mmc.c | 1560 | ||||
| -rw-r--r-- | drivers/mmc/host/bcm2835.c | 17 | ||||
| -rw-r--r-- | drivers/mmc/host/cqhci-core.c | 11 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-brcmstb.c | 276 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-iproc.c | 1 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-of-dwcmshc.c | 60 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-pltfm.c | 8 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-pltfm.h | 3 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci.c | 51 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci.h | 9 |
24 files changed, 2440 insertions, 204 deletions
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index dd6cffc0df72..f377c7705e9a 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -218,6 +218,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, @@ -927,7 +934,10 @@ static int mmc_blk_part_switch_pre(struct mmc_card *card, if ((part_type & mask) == rpmb) { if (card->ext_csd.cmdq_en) { - ret = mmc_cmdq_disable(card); + if (mmc_card_sd(card)) + ret = mmc_sd_cmdq_disable(card); + else + ret = mmc_cmdq_disable(card); if (ret) return ret; } @@ -946,8 +956,12 @@ static int mmc_blk_part_switch_post(struct mmc_card *card, if ((part_type & mask) == rpmb) { mmc_retune_unpause(card->host); - if (card->reenable_cmdq && !card->ext_csd.cmdq_en) - ret = mmc_cmdq_enable(card); + if (card->reenable_cmdq && !card->ext_csd.cmdq_en) { + if (mmc_card_sd(card)) + ret = mmc_sd_cmdq_enable(card); + else + ret = mmc_cmdq_enable(card); + } } return ret; @@ -1158,7 +1172,10 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req) switch (mq_rq->drv_op) { case MMC_DRV_OP_IOCTL: if (card->ext_csd.cmdq_en) { - ret = mmc_cmdq_disable(card); + if (mmc_card_sd(card)) + ret = mmc_sd_cmdq_disable(card); + else + ret = mmc_cmdq_disable(card); if (ret) break; } @@ -1176,8 +1193,12 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req) /* Always switch back to main area after RPMB access */ if (rpmb_ioctl) mmc_blk_part_switch(card, 0); - else if (card->reenable_cmdq && !card->ext_csd.cmdq_en) - mmc_cmdq_enable(card); + else if (card->reenable_cmdq && !card->ext_csd.cmdq_en) { + if (mmc_card_sd(card)) + mmc_sd_cmdq_enable(card); + else + mmc_cmdq_enable(card); + } break; case MMC_DRV_OP_BOOT_WP: ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP, @@ -1219,12 +1240,26 @@ static void mmc_blk_issue_erase_rq(struct mmc_queue *mq, struct request *req, sector_t from; int err = 0; blk_status_t status = BLK_STS_OK; + bool restart_cmdq = false; if (!mmc_card_can_erase(card)) { status = BLK_STS_NOTSUPP; goto fail; } + /* + * Only Discard ops are supported with SD cards in CQ mode + * (SD Physical Spec v9.00 4.19.2) + */ + if (mmc_card_sd(card) && card->ext_csd.cmdq_en && erase_arg != SD_DISCARD_ARG) { + restart_cmdq = true; + err = mmc_sd_cmdq_disable(card); + if (err) { + status = BLK_STS_IOERR; + goto fail; + } + } + from = blk_rq_pos(req); nr = blk_rq_sectors(req); @@ -1245,6 +1280,11 @@ static void mmc_blk_issue_erase_rq(struct mmc_queue *mq, struct request *req, status = BLK_STS_IOERR; else mmc_blk_reset_success(md, type); + + if (restart_cmdq) + err = mmc_sd_cmdq_enable(card); + if (err) + status = BLK_STS_IOERR; fail: blk_mq_end_request(req, status); } @@ -1567,6 +1607,7 @@ static void mmc_blk_cqe_complete_rq(struct mmc_queue *mq, struct request *req) struct request_queue *q = req->q; struct mmc_host *host = mq->card->host; enum mmc_issue_type issue_type = mmc_issue_type(mq, req); + bool write = req_op(req) == REQ_OP_WRITE; unsigned long flags; bool put_card; int err; @@ -1598,6 +1639,8 @@ static void mmc_blk_cqe_complete_rq(struct mmc_queue *mq, struct request *req) spin_lock_irqsave(&mq->lock, flags); + if (write) + mq->pending_writes--; mq->in_flight[issue_type] -= 1; put_card = (mmc_tot_in_flight(mq) == 0); @@ -2011,7 +2054,7 @@ static void mmc_blk_mq_rw_recovery(struct mmc_queue *mq, struct request *req) return; } - if (rq_data_dir(req) == READ && brq->data.blocks > + if (0 && rq_data_dir(req) == READ && brq->data.blocks > queue_physical_block_size(mq->queue) >> 9) { /* Read one (native) sector at a time */ mmc_blk_read_single(mq, req); @@ -2119,6 +2162,8 @@ static void mmc_blk_mq_complete_rq(struct mmc_queue *mq, struct request *req) struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req); unsigned int nr_bytes = mqrq->brq.data.bytes_xfered; + if (req_op(req) == REQ_OP_WRITE) + mq->pending_writes--; if (nr_bytes) { if (blk_update_request(req, BLK_STS_OK, nr_bytes)) blk_mq_requeue_request(req, true); @@ -2213,13 +2258,17 @@ static void mmc_blk_mq_poll_completion(struct mmc_queue *mq, mmc_blk_urgent_bkops(mq, mqrq); } -static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, enum mmc_issue_type issue_type) +static void mmc_blk_mq_dec_in_flight(struct mmc_queue *mq, enum mmc_issue_type issue_type, + bool write) { unsigned long flags; bool put_card; spin_lock_irqsave(&mq->lock, flags); + if (write) + mq->pending_writes--; + mq->in_flight[issue_type] -= 1; put_card = (mmc_tot_in_flight(mq) == 0); @@ -2234,6 +2283,7 @@ static void mmc_blk_mq_post_req(struct mmc_queue *mq, struct request *req, bool can_sleep) { enum mmc_issue_type issue_type = mmc_issue_type(mq, req); + bool write = req_op(req) == REQ_OP_WRITE; struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req); struct mmc_request *mrq = &mqrq->brq.mrq; struct mmc_host *host = mq->card->host; @@ -2253,7 +2303,7 @@ static void mmc_blk_mq_post_req(struct mmc_queue *mq, struct request *req, blk_mq_complete_request(req); } - mmc_blk_mq_dec_in_flight(mq, issue_type); + mmc_blk_mq_dec_in_flight(mq, issue_type, write); } void mmc_blk_mq_recovery(struct mmc_queue *mq) @@ -3315,6 +3365,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. @@ -3322,7 +3374,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); @@ -3337,6 +3398,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; diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 1cf64e0952fb..6da9484c13b1 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -266,6 +266,8 @@ static void mmc_release_card(struct device *dev) sdio_free_common_cis(card); + kfree(card->ext_reg_buf); + kfree(card->info); kfree(card); diff --git a/drivers/mmc/core/card.h b/drivers/mmc/core/card.h index 9cbdd240c3a7..f32955c26d1a 100644 --- a/drivers/mmc/core/card.h +++ b/drivers/mmc/core/card.h @@ -88,11 +88,13 @@ struct mmc_fixup { #define CID_MANFID_GIGASTONE 0x12 #define CID_MANFID_MICRON 0x13 #define CID_MANFID_SAMSUNG 0x15 +#define CID_MANFID_SAMSUNG_SD 0x1b #define CID_MANFID_APACER 0x27 #define CID_MANFID_SWISSBIT 0x5D #define CID_MANFID_KINGSTON 0x70 #define CID_MANFID_HYNIX 0x90 #define CID_MANFID_KINGSTON_SD 0x9F +#define CID_MANFID_LONGSYS_SD 0xAD #define CID_MANFID_NUMONYX 0xFE #define END_FIXUP { NULL } @@ -295,6 +297,11 @@ static inline int mmc_card_broken_sd_poweroff_notify(const struct mmc_card *c) return c->quirks & MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY; } +static inline int mmc_card_working_sd_cq(const struct mmc_card *c) +{ + return c->quirks & MMC_QUIRK_WORKING_SD_CQ; +} + static inline int mmc_card_no_uhs_ddr50_tuning(const struct mmc_card *c) { return c->quirks & MMC_QUIRK_NO_UHS_DDR50_TUNING; diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 874c6fe92855..749660629542 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -463,6 +463,7 @@ int mmc_cqe_start_req(struct mmc_host *host, struct mmc_request *mrq) goto out_err; trace_mmc_request_start(host, mrq); + led_trigger_event(host->led, LED_FULL); return 0; @@ -550,10 +551,18 @@ int mmc_cqe_recovery(struct mmc_host *host) * Recovery is expected seldom, if at all, but it reduces performance, * so make sure it is not completely silent. */ - pr_warn("%s: running CQE recovery\n", mmc_hostname(host)); + pr_warn_ratelimited("%s: running CQE recovery\n", mmc_hostname(host)); host->cqe_ops->cqe_recovery_start(host); + err = mmc_detect_card_removed(host); + if (err) { + host->cqe_ops->cqe_recovery_finish(host); + host->cqe_ops->cqe_off(host); + mmc_retune_release(host); + return err; + } + memset(&cmd, 0, sizeof(cmd)); cmd.opcode = MMC_STOP_TRANSMISSION; cmd.flags = MMC_RSP_R1B_NO_CRC | MMC_CMD_AC; /* Ignore CRC */ @@ -563,7 +572,11 @@ int mmc_cqe_recovery(struct mmc_host *host) mmc_poll_for_busy(host->card, MMC_CQE_RECOVERY_TIMEOUT, true, MMC_BUSY_IO); memset(&cmd, 0, sizeof(cmd)); - cmd.opcode = MMC_CMDQ_TASK_MGMT; + if (mmc_card_sd(host->card)) + cmd.opcode = SD_CMDQ_TASK_MGMT; + else + cmd.opcode = MMC_CMDQ_TASK_MGMT; + cmd.arg = 1; /* Discard entire queue */ cmd.flags = MMC_RSP_R1B_NO_CRC | MMC_CMD_AC; /* Ignore CRC */ cmd.busy_timeout = MMC_CQE_RECOVERY_TIMEOUT; @@ -1838,7 +1851,8 @@ EXPORT_SYMBOL(mmc_erase); bool mmc_card_can_erase(struct mmc_card *card) { - return (card->csd.cmdclass & CCC_ERASE && card->erase_size); + return (card->csd.cmdclass & CCC_ERASE && card->erase_size) && + !(card->quirks & MMC_QUIRK_ERASE_BROKEN); } EXPORT_SYMBOL(mmc_card_can_erase); diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index f14671ea5716..09ab3fa7fc25 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -271,7 +271,7 @@ EXPORT_SYMBOL(mmc_of_parse_clk_phase); int mmc_of_parse(struct mmc_host *host) { struct device *dev = host->parent; - u32 bus_width, drv_type, cd_debounce_delay_ms; + u32 bus_width, drv_type, cd_debounce_delay_ms, cq_allow; int ret; if (!dev || !dev_fwnode(dev)) @@ -406,6 +406,15 @@ int mmc_of_parse(struct mmc_host *host) host->caps2 &= ~(MMC_CAP2_HS400_1_8V | MMC_CAP2_HS400_1_2V | MMC_CAP2_HS400_ES); + cq_allow = 0; + /* + * Downstream property - if a u32 and 2 instead of a bool, + * trust most A2 SD cards claiming CQ support. + */ + device_property_read_u32(dev, "supports-cqe", &cq_allow); + if (cq_allow == 2) + host->caps2 |= MMC_CAP2_SD_CQE_PERMISSIVE; + /* Must be after "non-removable" check */ if (device_property_read_u32(dev, "fixed-emmc-driver-type", &drv_type) == 0) { if (host->caps & MMC_CAP_NONREMOVABLE) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 5be9b42d5057..5468bdb9d341 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1667,6 +1667,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, card->ocr = ocr; card->type = MMC_TYPE_MMC; card->rca = 1; + card->max_posted_writes = 1; memcpy(card->raw_cid, cid, sizeof(card->raw_cid)); } @@ -1925,13 +1926,14 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, host->cqe_enabled = true; if (card->ext_csd.cmdq_en) { - pr_info("%s: Command Queue Engine enabled\n", - mmc_hostname(host)); + pr_info("%s: Command Queue Engine enabled, %u tags\n", + mmc_hostname(host), card->ext_csd.cmdq_depth); } else { host->hsq_enabled = true; pr_info("%s: Host Software Queue enabled\n", mmc_hostname(host)); } + card->max_posted_writes = card->ext_csd.cmdq_depth; } } diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c index 284856c8f655..feda8ddbd8b6 100644 --- a/drivers/mmc/core/queue.c +++ b/drivers/mmc/core/queue.c @@ -266,6 +266,11 @@ static blk_status_t mmc_mq_queue_rq(struct blk_mq_hw_ctx *hctx, spin_unlock_irq(&mq->lock); return BLK_STS_RESOURCE; } + if (!host->hsq_enabled && host->cqe_enabled && req_op(req) == REQ_OP_WRITE && + mq->pending_writes >= card->max_posted_writes) { + spin_unlock_irq(&mq->lock); + return BLK_STS_RESOURCE; + } break; default: /* @@ -282,6 +287,8 @@ static blk_status_t mmc_mq_queue_rq(struct blk_mq_hw_ctx *hctx, /* Parallel dispatch of requests is not supported at the moment */ mq->busy = true; + if (req_op(req) == REQ_OP_WRITE) + mq->pending_writes++; mq->in_flight[issue_type] += 1; get_card = (mmc_tot_in_flight(mq) == 1); cqe_retune_ok = (mmc_cqe_qcnt(mq) == 1); @@ -321,6 +328,8 @@ static blk_status_t mmc_mq_queue_rq(struct blk_mq_hw_ctx *hctx, bool put_card = false; spin_lock_irq(&mq->lock); + if (req_op(req) == REQ_OP_WRITE) + mq->pending_writes--; mq->in_flight[issue_type] -= 1; if (mmc_tot_in_flight(mq) == 0) put_card = true; diff --git a/drivers/mmc/core/queue.h b/drivers/mmc/core/queue.h index 1498840a4ea0..39180d97911b 100644 --- a/drivers/mmc/core/queue.h +++ b/drivers/mmc/core/queue.h @@ -79,6 +79,7 @@ struct mmc_queue { struct request_queue *queue; spinlock_t lock; int in_flight[MMC_ISSUE_MAX]; + int pending_writes; unsigned int cqe_busy; #define MMC_CQE_DCMD_BUSY BIT(0) bool busy; diff --git a/drivers/mmc/core/quirks.h b/drivers/mmc/core/quirks.h index c417ed34c057..d975d62b3734 100644 --- a/drivers/mmc/core/quirks.h +++ b/drivers/mmc/core/quirks.h @@ -18,20 +18,33 @@ static const struct mmc_fixup __maybe_unused mmc_sd_fixups[] = { /* * Kingston Canvas Go! Plus microSD cards never finish SD cache flush. - * This has so far only been observed on cards from 11/2019, while new - * cards from 2023/05 do not exhibit this behavior. + * This has been observed on cards from 2019/11 and 2021/11, while new + * cards from 2023/05 and 2024/08 do not exhibit this behavior. */ - _FIXUP_EXT("SD64G", CID_MANFID_KINGSTON_SD, 0x5449, 2019, 11, - 0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd, - MMC_QUIRK_BROKEN_SD_CACHE, EXT_CSD_REV_ANY), + _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_KINGSTON_SD, 0x5449, 2019, + CID_MONTH_ANY, 0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, + add_quirk_sd, MMC_QUIRK_BROKEN_SD_CACHE, EXT_CSD_REV_ANY), + + _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_KINGSTON_SD, 0x5449, 2020, + CID_MONTH_ANY, 0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, + add_quirk_sd, MMC_QUIRK_BROKEN_SD_CACHE, EXT_CSD_REV_ANY), + + _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_KINGSTON_SD, 0x5449, 2021, + CID_MONTH_ANY, 0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, + add_quirk_sd, MMC_QUIRK_BROKEN_SD_CACHE, EXT_CSD_REV_ANY), + + _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_KINGSTON_SD, 0x5449, 2022, + CID_MONTH_ANY, 0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, + add_quirk_sd, MMC_QUIRK_BROKEN_SD_CACHE, EXT_CSD_REV_ANY), /* * GIGASTONE Gaming Plus microSD cards manufactured on 02/2022 never * clear Flush Cache bit and set Poweroff Notification Ready bit. */ - _FIXUP_EXT("ASTC", CID_MANFID_GIGASTONE, 0x3456, 2022, 2, - 0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd, - MMC_QUIRK_BROKEN_SD_CACHE | MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY, + _FIXUP_EXT("ASTC", CID_MANFID_GIGASTONE, 0x3456, 2022, 2, 0, -1ull, + SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd, + MMC_QUIRK_BROKEN_SD_CACHE | + MMC_QUIRK_BROKEN_SD_POWEROFF_NOTIFY, EXT_CSD_REV_ANY), /* @@ -40,8 +53,8 @@ static const struct mmc_fixup __maybe_unused mmc_sd_fixups[] = { * only been observed on cards manufactured on 01/2019 that are using * Bay Trail host controllers. */ - _FIXUP_EXT("0016G", CID_MANFID_SWISSBIT, 0x5342, 2019, 1, - 0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd, + _FIXUP_EXT("0016G", CID_MANFID_SWISSBIT, 0x5342, 2019, 1, 0, -1ull, + SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd, MMC_QUIRK_NO_UHS_DDR50_TUNING, EXT_CSD_REV_ANY), /* @@ -50,13 +63,39 @@ static const struct mmc_fixup __maybe_unused mmc_sd_fixups[] = { MMC_FIXUP(CID_NAME_ANY, CID_MANFID_SANDISK_SD, 0x5344, add_quirk_sd, MMC_QUIRK_BROKEN_SD_DISCARD), + /* + * Samsung Pro Plus/EVO Plus/Pro Ultimate SD cards (2023) claim to cache + * flush OK, but become unresponsive afterwards. + */ + _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_SAMSUNG_SD, 0x534d, 2023, CID_MONTH_ANY, + 0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd, + MMC_QUIRK_BROKEN_SD_CACHE, EXT_CSD_REV_ANY), + + /* + * Early Sandisk Extreme and Extreme Pro A2 cards never finish SD cache + * flush in CQ mode. Latest card date this was seen on is 10/2020. + */ + _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_SANDISK_SD, 0x5344, 2019, CID_MONTH_ANY, + 0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd, + MMC_QUIRK_BROKEN_SD_CACHE, EXT_CSD_REV_ANY), + + _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_SANDISK_SD, 0x5344, 2020, CID_MONTH_ANY, + 0, -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd, + MMC_QUIRK_BROKEN_SD_CACHE, EXT_CSD_REV_ANY), + + /* SD A2 allow-list - only trust CQ on these cards */ + /* Raspberry Pi A2 cards */ + _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_LONGSYS_SD, 0x4c53, CID_YEAR_ANY, CID_MONTH_ANY, + cid_rev(1, 0, 0, 0), -1ull, SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_sd, + MMC_QUIRK_WORKING_SD_CQ, EXT_CSD_REV_ANY), + END_FIXUP }; static const struct mmc_fixup __maybe_unused mmc_blk_fixups[] = { -#define INAND_CMD38_ARG_EXT_CSD 113 -#define INAND_CMD38_ARG_ERASE 0x00 -#define INAND_CMD38_ARG_TRIM 0x01 +#define INAND_CMD38_ARG_EXT_CSD 113 +#define INAND_CMD38_ARG_ERASE 0x00 +#define INAND_CMD38_ARG_TRIM 0x01 #define INAND_CMD38_ARG_SECERASE 0x80 #define INAND_CMD38_ARG_SECTRIM1 0x81 #define INAND_CMD38_ARG_SECTRIM2 0x88 @@ -153,6 +192,29 @@ static const struct mmc_fixup __maybe_unused mmc_blk_fixups[] = { MMC_FIXUP("M62704", CID_MANFID_KINGSTON, 0x0100, add_quirk_mmc, MMC_QUIRK_TRIM_BROKEN), + /* + * Some SD cards reports discard support while they don't + */ + MMC_FIXUP(CID_NAME_ANY, CID_MANFID_SANDISK_SD, 0x5344, add_quirk_sd, + MMC_QUIRK_BROKEN_SD_DISCARD), + + /* + * 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), + + /* + * Larger Integral SD cards using rebranded Phison controllers trash + * nearby flash blocks after erases. + */ + MMC_FIXUP("SD64G", 0x27, 0x5048, add_quirk, MMC_QUIRK_ERASE_BROKEN), + MMC_FIXUP("SD128", 0x27, 0x5048, add_quirk, MMC_QUIRK_ERASE_BROKEN), + MMC_FIXUP("SD256", 0x27, 0x5048, add_quirk, MMC_QUIRK_ERASE_BROKEN), + MMC_FIXUP("SD512", 0x27, 0x5048, add_quirk, MMC_QUIRK_ERASE_BROKEN), + END_FIXUP }; @@ -161,19 +223,18 @@ static const struct mmc_fixup __maybe_unused mmc_ext_csd_fixups[] = { * Certain Hynix eMMC 4.41 cards might get broken when HPI feature * is used so disable the HPI feature for such buggy cards. */ - MMC_FIXUP_EXT_CSD_REV(CID_NAME_ANY, CID_MANFID_HYNIX, - 0x014a, add_quirk, MMC_QUIRK_BROKEN_HPI, 5), + MMC_FIXUP_EXT_CSD_REV(CID_NAME_ANY, CID_MANFID_HYNIX, 0x014a, add_quirk, + MMC_QUIRK_BROKEN_HPI, 5), /* * Certain Micron (Numonyx) eMMC 4.5 cards might get broken when HPI * feature is used so disable the HPI feature for such buggy cards. */ - MMC_FIXUP_EXT_CSD_REV(CID_NAME_ANY, CID_MANFID_NUMONYX, - 0x014e, add_quirk, MMC_QUIRK_BROKEN_HPI, 6), + MMC_FIXUP_EXT_CSD_REV(CID_NAME_ANY, CID_MANFID_NUMONYX, 0x014e, + add_quirk, MMC_QUIRK_BROKEN_HPI, 6), END_FIXUP }; - static const struct mmc_fixup __maybe_unused sdio_fixup_methods[] = { SDIO_FIXUP(SDIO_VENDOR_ID_TI_WL1251, SDIO_DEVICE_ID_TI_WL1251, add_quirk, MMC_QUIRK_NONSTD_FUNC_IF), @@ -181,14 +242,14 @@ static const struct mmc_fixup __maybe_unused sdio_fixup_methods[] = { SDIO_FIXUP(SDIO_VENDOR_ID_TI_WL1251, SDIO_DEVICE_ID_TI_WL1251, add_quirk, MMC_QUIRK_DISABLE_CD), - SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271, - add_quirk, MMC_QUIRK_NONSTD_FUNC_IF), + SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271, add_quirk, + MMC_QUIRK_NONSTD_FUNC_IF), - SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271, - add_quirk, MMC_QUIRK_DISABLE_CD), + SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271, add_quirk, + MMC_QUIRK_DISABLE_CD), - SDIO_FIXUP(SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_CW1200, - add_quirk, MMC_QUIRK_BROKEN_BYTE_MODE_512), + SDIO_FIXUP(SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_CW1200, add_quirk, + MMC_QUIRK_BROKEN_BYTE_MODE_512), SDIO_FIXUP(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8797_F0, add_quirk, MMC_QUIRK_BROKEN_IRQ_POLLING), @@ -204,8 +265,8 @@ static const struct mmc_fixup __maybe_unused sdio_card_init_methods[] = { SDIO_FIXUP_COMPATIBLE("silabs,wf200", add_quirk, MMC_QUIRK_BROKEN_BYTE_MODE_512 | - MMC_QUIRK_LENIENT_FN0 | - MMC_QUIRK_BLKSZ_FOR_BYTE_MODE), + MMC_QUIRK_LENIENT_FN0 | + MMC_QUIRK_BLKSZ_FOR_BYTE_MODE), END_FIXUP }; @@ -235,8 +296,7 @@ static inline void mmc_fixup_device(struct mmc_card *card, if (f->manfid != CID_MANFID_ANY && f->manfid != card->cid.manfid) continue; - if (f->oemid != CID_OEMID_ANY && - f->oemid != card->cid.oemid) + if (f->oemid != CID_OEMID_ANY && f->oemid != card->cid.oemid) continue; if (f->name != CID_NAME_ANY && strncmp(f->name, card->cid.prod_name, diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index ec02067f03c5..67b82a6ea09d 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -730,7 +730,8 @@ MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid); MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial); MMC_DEV_ATTR(ocr, "0x%08x\n", card->ocr); MMC_DEV_ATTR(rca, "0x%04x\n", card->rca); - +MMC_DEV_ATTR(ext_perf, "%02x\n", card->ext_perf.feature_support); +MMC_DEV_ATTR(ext_power, "%02x\n", card->ext_power.feature_support); static ssize_t mmc_dsr_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -792,6 +793,8 @@ static struct attribute *sd_std_attrs[] = { &dev_attr_ocr.attr, &dev_attr_rca.attr, &dev_attr_dsr.attr, + &dev_attr_ext_perf.attr, + &dev_attr_ext_power.attr, NULL, }; @@ -1034,98 +1037,16 @@ static bool mmc_sd_card_using_v18(struct mmc_card *card) (SD_MODE_UHS_SDR50 | SD_MODE_UHS_SDR104 | SD_MODE_UHS_DDR50); } -static int sd_write_ext_reg(struct mmc_card *card, u8 fno, u8 page, u16 offset, - u8 reg_data) -{ - struct mmc_host *host = card->host; - struct mmc_request mrq = {}; - struct mmc_command cmd = {}; - struct mmc_data data = {}; - struct scatterlist sg; - u8 *reg_buf; - - reg_buf = kzalloc(512, GFP_KERNEL); - if (!reg_buf) - return -ENOMEM; - - mrq.cmd = &cmd; - mrq.data = &data; - - /* - * Arguments of CMD49: - * [31:31] MIO (0 = memory). - * [30:27] FNO (function number). - * [26:26] MW - mask write mode (0 = disable). - * [25:18] page number. - * [17:9] offset address. - * [8:0] length (0 = 1 byte). - */ - cmd.arg = fno << 27 | page << 18 | offset << 9; - - /* The first byte in the buffer is the data to be written. */ - reg_buf[0] = reg_data; - - data.flags = MMC_DATA_WRITE; - data.blksz = 512; - data.blocks = 1; - data.sg = &sg; - data.sg_len = 1; - sg_init_one(&sg, reg_buf, 512); - - cmd.opcode = SD_WRITE_EXTR_SINGLE; - cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; - - mmc_set_data_timeout(&data, card); - mmc_wait_for_req(host, &mrq); - - kfree(reg_buf); - - /* - * Note that, the SD card is allowed to signal busy on DAT0 up to 1s - * after the CMD49. Although, let's leave this to be managed by the - * caller. - */ - - if (cmd.error) - return cmd.error; - if (data.error) - return data.error; - - return 0; -} - -static int sd_read_ext_reg(struct mmc_card *card, u8 fno, u8 page, - u16 offset, u16 len, u8 *reg_buf) -{ - u32 cmd_args; - - /* - * Command arguments of CMD48: - * [31:31] MIO (0 = memory). - * [30:27] FNO (function number). - * [26:26] reserved (0). - * [25:18] page number. - * [17:9] offset address. - * [8:0] length (0 = 1 byte, 1ff = 512 bytes). - */ - cmd_args = fno << 27 | page << 18 | offset << 9 | (len -1); - - return mmc_send_adtc_data(card, card->host, SD_READ_EXTR_SINGLE, - cmd_args, reg_buf, 512); -} - static int sd_parse_ext_reg_power(struct mmc_card *card, u8 fno, u8 page, u16 offset) { int err; u8 *reg_buf; - reg_buf = kzalloc(512, GFP_KERNEL); - if (!reg_buf) - return -ENOMEM; + reg_buf = card->ext_reg_buf; /* Read the extension register for power management function. */ - err = sd_read_ext_reg(card, fno, page, offset, 512, reg_buf); + err = mmc_sd_read_ext_reg(card, fno, page, offset, 512, reg_buf); if (err) { pr_warn("%s: error %d reading PM func of ext reg\n", mmc_hostname(card->host), err); @@ -1152,7 +1073,6 @@ static int sd_parse_ext_reg_power(struct mmc_card *card, u8 fno, u8 page, card->ext_power.offset = offset; out: - kfree(reg_buf); return err; } @@ -1162,11 +1082,9 @@ static int sd_parse_ext_reg_perf(struct mmc_card *card, u8 fno, u8 page, int err; u8 *reg_buf; - reg_buf = kzalloc(512, GFP_KERNEL); - if (!reg_buf) - return -ENOMEM; + reg_buf = card->ext_reg_buf; - err = sd_read_ext_reg(card, fno, page, offset, 512, reg_buf); + err = mmc_sd_read_ext_reg(card, fno, page, offset, 512, reg_buf); if (err) { pr_warn("%s: error %d reading PERF func of ext reg\n", mmc_hostname(card->host), err); @@ -1192,16 +1110,34 @@ static int sd_parse_ext_reg_perf(struct mmc_card *card, u8 fno, u8 page, if ((reg_buf[4] & BIT(0)) && !mmc_card_broken_sd_cache(card)) card->ext_perf.feature_support |= SD_EXT_PERF_CACHE; - /* Command queue support indicated via queue depth bits (0 to 4). */ - if (reg_buf[6] & 0x1f) + /* + * Command queue support indicated via queue depth bits (0 to 4). + * Qualify this with the other mandatory required features. + */ + if (reg_buf[6] & 0x1f && card->ext_power.feature_support & SD_EXT_POWER_OFF_NOTIFY && + card->ext_perf.feature_support & SD_EXT_PERF_CACHE) { card->ext_perf.feature_support |= SD_EXT_PERF_CMD_QUEUE; + card->ext_csd.cmdq_depth = reg_buf[6] & 0x1f; + card->ext_csd.cmdq_support = true; + pr_debug("%s: Command Queue supported depth %u\n", + mmc_hostname(card->host), + card->ext_csd.cmdq_depth); + /* + * If CQ is enabled, there is a contract between host and card such that + * VDD will be maintained and removed only if a power off notification + * is provided. An SD card in an accessible slot means surprise removal + * is a possibility. As a middle ground, keep the default maximum of 1 + * posted write unless the card is "hardwired". + */ + if (!mmc_card_is_removable(card->host)) + card->max_posted_writes = card->ext_csd.cmdq_depth; + } card->ext_perf.fno = fno; card->ext_perf.page = page; card->ext_perf.offset = offset; out: - kfree(reg_buf); return err; } @@ -1256,7 +1192,7 @@ static int sd_parse_ext_reg(struct mmc_card *card, u8 *gen_info_buf, return 0; } -static int sd_read_ext_regs(struct mmc_card *card) +static int mmc_sd_read_ext_regs(struct mmc_card *card) { int err, i; u8 num_ext, *gen_info_buf; @@ -1268,15 +1204,21 @@ static int sd_read_ext_regs(struct mmc_card *card) if (!(card->scr.cmds & SD_SCR_CMD48_SUPPORT)) return 0; - gen_info_buf = kzalloc(512, GFP_KERNEL); + gen_info_buf = kzalloc(1024, GFP_KERNEL); if (!gen_info_buf) return -ENOMEM; + card->ext_reg_buf = kzalloc(512, GFP_KERNEL); + if (!card->ext_reg_buf) { + err = -ENOMEM; + goto out; + } + /* * Read 512 bytes of general info, which is found at function number 0, * at page 0 and with no offset. */ - err = sd_read_ext_reg(card, 0, 0, 0, 512, gen_info_buf); + err = mmc_sd_read_ext_reg(card, 0, 0, 0, 512, gen_info_buf); if (err) { pr_err("%s: error %d reading general info of SD ext reg\n", mmc_hostname(card->host), err); @@ -1293,14 +1235,23 @@ static int sd_read_ext_regs(struct mmc_card *card) num_ext = gen_info_buf[4]; /* - * We only support revision 0 and limit it to 512 bytes for simplicity. + * We only support revision 0 and up to the spec-defined maximum of 1K. * No matter what, let's return zero to allow us to continue using the * card, even if we can't support the features from the SD function * extensions registers. */ - if (rev != 0 || len > 512) { - pr_warn("%s: non-supported SD ext reg layout\n", - mmc_hostname(card->host)); + if (rev != 0 || len > 1024) { + pr_warn("%s: non-supported SD ext reg layout rev %u length %u\n", + mmc_hostname(card->host), rev, len); + goto out; + } + + /* If the General Information block spills into the next page, read the rest */ + if (len > 512) + err = mmc_sd_read_ext_reg(card, 0, 1, 0, 512, &gen_info_buf[512]); + if (err) { + pr_err("%s: error %d reading page 1 of general info of SD ext reg\n", + mmc_hostname(card->host), err); goto out; } @@ -1338,9 +1289,7 @@ static int sd_flush_cache(struct mmc_host *host) if (!sd_cache_enabled(host)) return 0; - reg_buf = kzalloc(512, GFP_KERNEL); - if (!reg_buf) - return -ENOMEM; + reg_buf = card->ext_reg_buf; /* * Set Flush Cache at bit 0 in the performance enhancement register at @@ -1350,7 +1299,7 @@ static int sd_flush_cache(struct mmc_host *host) page = card->ext_perf.page; offset = card->ext_perf.offset + 261; - err = sd_write_ext_reg(card, fno, page, offset, BIT(0)); + err = mmc_sd_write_ext_reg(card, fno, page, offset, BIT(0)); if (err) { pr_warn("%s: error %d writing Cache Flush bit\n", mmc_hostname(host), err); @@ -1366,7 +1315,7 @@ static int sd_flush_cache(struct mmc_host *host) * Read the Flush Cache bit. The card shall reset it, to confirm that * it's has completed the flushing of the cache. */ - err = sd_read_ext_reg(card, fno, page, offset, 1, reg_buf); + err = mmc_sd_read_ext_reg(card, fno, page, offset, 1, reg_buf); if (err) { pr_warn("%s: error %d reading Cache Flush bit\n", mmc_hostname(host), err); @@ -1376,26 +1325,20 @@ static int sd_flush_cache(struct mmc_host *host) if (reg_buf[0] & BIT(0)) err = -ETIMEDOUT; out: - kfree(reg_buf); return err; } static int sd_enable_cache(struct mmc_card *card) { - u8 *reg_buf; int err; card->ext_perf.feature_enabled &= ~SD_EXT_PERF_CACHE; - reg_buf = kzalloc(512, GFP_KERNEL); - if (!reg_buf) - return -ENOMEM; - /* * Set Cache Enable at bit 0 in the performance enhancement register at * 260 bytes offset. */ - err = sd_write_ext_reg(card, card->ext_perf.fno, card->ext_perf.page, + err = mmc_sd_write_ext_reg(card, card->ext_perf.fno, card->ext_perf.page, card->ext_perf.offset + 260, BIT(0)); if (err) { pr_warn("%s: error %d writing Cache Enable bit\n", @@ -1409,7 +1352,6 @@ static int sd_enable_cache(struct mmc_card *card) card->ext_perf.feature_enabled |= SD_EXT_PERF_CACHE; out: - kfree(reg_buf); return err; } @@ -1452,6 +1394,7 @@ retry: card->ocr = ocr; card->type = MMC_TYPE_SD; + card->max_posted_writes = 1; memcpy(card->raw_cid, cid, sizeof(card->raw_cid)); } @@ -1572,7 +1515,7 @@ retry: cont: if (!oldcard) { /* Read/parse the extension registers. */ - err = sd_read_ext_regs(card); + err = mmc_sd_read_ext_regs(card); if (err) goto free_card; } @@ -1584,13 +1527,45 @@ cont: goto free_card; } + /* Disallow command queueing on unvetted cards unless overridden */ + if (!(host->caps2 & MMC_CAP2_SD_CQE_PERMISSIVE) && !mmc_card_working_sd_cq(card)) + card->ext_csd.cmdq_support = false; + + /* Enable command queueing if supported */ + if (card->ext_csd.cmdq_support && host->caps2 & MMC_CAP2_CQE) { + /* + * Right now the MMC block layer uses DCMDs to issue + * cache-flush commands specific to eMMC devices. + * Turning off DCMD support avoids generating Illegal Command + * errors on SD, and flushing is instead done synchronously + * by mmc_blk_issue_flush(). + */ + host->caps2 &= ~MMC_CAP2_CQE_DCMD; + err = mmc_sd_cmdq_enable(card); + if (err && err != -EBADMSG) + goto free_card; + if (err) { + pr_warn("%s: Enabling CMDQ failed\n", + mmc_hostname(card->host)); + card->ext_csd.cmdq_support = false; + card->ext_csd.cmdq_depth = 0; + } + } + card->reenable_cmdq = card->ext_csd.cmdq_en; + if (!mmc_card_ult_capacity(card) && host->cqe_ops && !host->cqe_enabled) { err = host->cqe_ops->cqe_enable(host, card); if (!err) { host->cqe_enabled = true; - host->hsq_enabled = true; - pr_info("%s: Host Software Queue enabled\n", - mmc_hostname(host)); + + if (card->ext_csd.cmdq_en) { + pr_info("%s: Command Queue Engine enabled, %u tags\n", + mmc_hostname(host), card->ext_csd.cmdq_depth); + } else { + host->hsq_enabled = true; + pr_info("%s: Host Software Queue enabled\n", + mmc_hostname(host)); + } } } @@ -1663,7 +1638,7 @@ static int sd_busy_poweroff_notify_cb(void *cb_data, bool *busy) * one byte offset and is one byte long. The Power Off Notification * Ready is bit 0. */ - err = sd_read_ext_reg(card, card->ext_power.fno, card->ext_power.page, + err = mmc_sd_read_ext_reg(card, card->ext_power.fno, card->ext_power.page, card->ext_power.offset + 1, 1, data->reg_buf); if (err) { pr_warn("%s: error %d reading status reg of PM func\n", @@ -1689,7 +1664,7 @@ static int sd_poweroff_notify(struct mmc_card *card) * Set the Power Off Notification bit in the power management settings * register at 2 bytes offset. */ - err = sd_write_ext_reg(card, card->ext_power.fno, card->ext_power.page, + err = mmc_sd_write_ext_reg(card, card->ext_power.fno, card->ext_power.page, card->ext_power.offset + 2, BIT(0)); if (err) { pr_warn("%s: error %d writing Power Off Notify bit\n", diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c index cd86463dd306..5d03b6b6e69b 100644 --- a/drivers/mmc/core/sd_ops.c +++ b/drivers/mmc/core/sd_ops.c @@ -8,6 +8,7 @@ #include <linux/slab.h> #include <linux/types.h> #include <linux/export.h> +#include <linux/ktime.h> #include <linux/scatterlist.h> #include <linux/mmc/host.h> @@ -417,3 +418,136 @@ int mmc_app_sd_status(struct mmc_card *card, void *ssr) return 0; } + + +int mmc_sd_write_ext_reg(struct mmc_card *card, u8 fno, u8 page, u16 offset, + u8 reg_data) +{ + struct mmc_host *host = card->host; + struct mmc_request mrq = {}; + struct mmc_command cmd = {}; + struct mmc_data data = {}; + struct scatterlist sg; + u8 *reg_buf; + + reg_buf = card->ext_reg_buf; + memset(reg_buf, 0, 512); + + mrq.cmd = &cmd; + mrq.data = &data; + + /* + * Arguments of CMD49: + * [31:31] MIO (0 = memory). + * [30:27] FNO (function number). + * [26:26] MW - mask write mode (0 = disable). + * [25:18] page number. + * [17:9] offset address. + * [8:0] length (0 = 1 byte). + */ + cmd.arg = fno << 27 | page << 18 | offset << 9; + + /* The first byte in the buffer is the data to be written. */ + reg_buf[0] = reg_data; + + data.flags = MMC_DATA_WRITE; + data.blksz = 512; + data.blocks = 1; + data.sg = &sg; + data.sg_len = 1; + sg_init_one(&sg, reg_buf, 512); + + cmd.opcode = SD_WRITE_EXTR_SINGLE; + cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; + + mmc_set_data_timeout(&data, card); + mmc_wait_for_req(host, &mrq); + + /* + * Note that, the SD card is allowed to signal busy on DAT0 up to 1s + * after the CMD49. Although, let's leave this to be managed by the + * caller. + */ + + if (cmd.error) + return cmd.error; + if (data.error) + return data.error; + + return 0; +} + +int mmc_sd_read_ext_reg(struct mmc_card *card, u8 fno, u8 page, + u16 offset, u16 len, u8 *reg_buf) +{ + u32 cmd_args; + + /* + * Command arguments of CMD48: + * [31:31] MIO (0 = memory). + * [30:27] FNO (function number). + * [26:26] reserved (0). + * [25:18] page number. + * [17:9] offset address. + * [8:0] length (0 = 1 byte, 1ff = 512 bytes). + */ + cmd_args = fno << 27 | page << 18 | offset << 9 | (len - 1); + + return mmc_send_adtc_data(card, card->host, SD_READ_EXTR_SINGLE, + cmd_args, reg_buf, 512); +} + +static int mmc_sd_cmdq_switch(struct mmc_card *card, bool enable) +{ + int err; + u8 reg = 0; + u8 *reg_buf = card->ext_reg_buf; + ktime_t timeout; + /* + * SD offers two command queueing modes - sequential (in-order) and + * voluntary (out-of-order). Apps Class A2 performance is only + * guaranteed for voluntary CQ (bit 1 = 0), so use that in preference + * to sequential. + */ + if (enable) + reg = BIT(0); + + /* Performance enhancement register byte 262 controls command queueing */ + err = mmc_sd_write_ext_reg(card, card->ext_perf.fno, card->ext_perf.page, + card->ext_perf.offset + 262, reg); + if (err) + goto out; + + /* Poll the register - cards may have a lazy init/deinit sequence. */ + timeout = ktime_add_ms(ktime_get(), 10); + while (1) { + err = mmc_sd_read_ext_reg(card, card->ext_perf.fno, card->ext_perf.page, + card->ext_perf.offset + 262, 1, reg_buf); + if (err) + break; + if ((reg_buf[0] & BIT(0)) == reg) + break; + if (ktime_after(ktime_get(), timeout)) { + err = -EBADMSG; + break; + } + usleep_range(100, 200); + } +out: + if (!err) + card->ext_csd.cmdq_en = enable; + + return err; +} + +int mmc_sd_cmdq_enable(struct mmc_card *card) +{ + return mmc_sd_cmdq_switch(card, true); +} +EXPORT_SYMBOL_GPL(mmc_sd_cmdq_enable); + +int mmc_sd_cmdq_disable(struct mmc_card *card) +{ + return mmc_sd_cmdq_switch(card, false); +} +EXPORT_SYMBOL_GPL(mmc_sd_cmdq_disable); diff --git a/drivers/mmc/core/sd_ops.h b/drivers/mmc/core/sd_ops.h index 8fffc1b29757..db04885ecb0f 100644 --- a/drivers/mmc/core/sd_ops.h +++ b/drivers/mmc/core/sd_ops.h @@ -24,6 +24,12 @@ int mmc_app_sd_status(struct mmc_card *card, void *ssr); int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card); int mmc_send_ext_addr(struct mmc_host *host, u32 addr); void mmc_uhs2_prepare_cmd(struct mmc_host *host, struct mmc_request *mrq); +int mmc_sd_cmdq_enable(struct mmc_card *card); +int mmc_sd_cmdq_disable(struct mmc_card *card); +int mmc_sd_write_ext_reg(struct mmc_card *card, u8 fno, u8 page, u16 offset, + u8 reg_data); +int mmc_sd_read_ext_reg(struct mmc_card *card, u8 fno, u8 page, + u16 offset, u16 len, u8 *reg_buf); #endif diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 5cc415ba4f55..6a72ab170ccf 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -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 @@ -1056,6 +1085,7 @@ config MMC_SDHCI_BRCMSTB depends on ARCH_BRCMSTB || ARCH_BCM2835 || BMIPS_GENERIC || COMPILE_TEST depends on MMC_SDHCI_PLTFM select MMC_CQHCI + select OF_DYNAMIC default ARCH_BRCMSTB || BMIPS_GENERIC help This selects support for the SDIO/SD/MMC Host Controller on diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 5057fea8afb6..f0cb916d248f 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -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 diff --git a/drivers/mmc/host/bcm2835-mmc.c b/drivers/mmc/host/bcm2835-mmc.c new file mode 100644 index 000000000000..fec210b33231 --- /dev/null +++ b/drivers/mmc/host/bcm2835-mmc.c @@ -0,0 +1,1560 @@ +/* + * BCM2835 MMC host driver. + * + * Author: Gellert Weisz <[email protected]> + * Copyright 2014 + * + * Based on + * sdhci-bcm2708.c by Broadcom + * sdhci-bcm2835.c by Stephen Warren and Oleksandr Tymoshenko + * sdhci.c and sdhci-pci.c by Pierre Ossman + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/io.h> +#include <linux/mmc/mmc.h> +#include <linux/mmc/host.h> +#include <linux/mmc/sd.h> +#include <linux/scatterlist.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <linux/err.h> +#include <linux/blkdev.h> +#include <linux/dmaengine.h> +#include <linux/dma-mapping.h> +#include <linux/of_dma.h> +#include <linux/swiotlb.h> + +#include "sdhci.h" + + +#define DRIVER_NAME "mmc-bcm2835" + +#define DBG(f, x...) \ +pr_debug(DRIVER_NAME " [%s()]: " f, __func__, ## x) + +#ifndef CONFIG_MMC_BCM2835_DMA + #define FORCE_PIO +#endif + + +/* the inclusive limit in bytes under which PIO will be used instead of DMA */ +#ifdef CONFIG_MMC_BCM2835_PIO_DMA_BARRIER +#define PIO_DMA_BARRIER CONFIG_MMC_BCM2835_PIO_DMA_BARRIER +#else +#define PIO_DMA_BARRIER 00 +#endif + +#define MIN_FREQ 400000 +#define TIMEOUT_VAL 0xE +#define BCM2835_SDHCI_WRITE_DELAY(f) (((2 * 1000000) / f) + 1) + + +unsigned mmc_debug; +unsigned mmc_debug2; + +struct bcm2835_host { + spinlock_t lock; + + void __iomem *ioaddr; + u32 bus_addr; + + struct mmc_host *mmc; + + u32 timeout; + + int clock; /* Current clock speed */ + u8 pwr; /* Current voltage */ + + unsigned int max_clk; /* Max possible freq */ + unsigned int timeout_clk; /* Timeout freq (KHz) */ + unsigned int clk_mul; /* Clock Muliplier value */ + + struct tasklet_struct finish_tasklet; /* Tasklet structures */ + + struct timer_list timer; /* Timer for timeouts */ + + struct sg_mapping_iter sg_miter; /* SG state for PIO */ + unsigned int blocks; /* remaining PIO blocks */ + + int irq; /* Device IRQ */ + + + u32 ier; /* cached registers */ + + struct mmc_request *mrq; /* Current request */ + struct mmc_command *cmd; /* Current command */ + struct mmc_data *data; /* Current data request */ + unsigned int data_early:1; /* Data finished before cmd */ + + wait_queue_head_t buf_ready_int; /* Waitqueue for Buffer Read Ready interrupt */ + + u32 shadow; + + /*DMA part*/ + struct dma_chan *dma_chan_rxtx; /* DMA channel for reads and writes */ + struct dma_slave_config dma_cfg_rx; + struct dma_slave_config dma_cfg_tx; + struct dma_async_tx_descriptor *tx_desc; /* descriptor */ + + bool have_dma; + bool use_dma; + bool wait_for_dma; + /*end of DMA part*/ + + int max_delay; /* maximum length of time spent waiting */ + + int flags; /* Host attributes */ +#define SDHCI_REQ_USE_DMA (1<<2) /* Use DMA for this req. */ +#define SDHCI_DEVICE_DEAD (1<<3) /* Device unresponsive */ +#define SDHCI_AUTO_CMD12 (1<<6) /* Auto CMD12 support */ +#define SDHCI_AUTO_CMD23 (1<<7) /* Auto CMD23 support */ +#define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */ + + u32 overclock_50; /* frequency to use when 50MHz is requested (in MHz) */ + u32 max_overclock; /* Highest reported */ +}; + + +static inline void bcm2835_mmc_writel(struct bcm2835_host *host, u32 val, int reg, int from) +{ + unsigned delay; + lockdep_assert_held_once(&host->lock); + writel(val, host->ioaddr + reg); + udelay(BCM2835_SDHCI_WRITE_DELAY(max(host->clock, MIN_FREQ))); + + delay = ((mmc_debug >> 16) & 0xf) << ((mmc_debug >> 20) & 0xf); + if (delay && !((1<<from) & mmc_debug2)) + udelay(delay); +} + +static inline void mmc_raw_writel(struct bcm2835_host *host, u32 val, int reg) +{ + unsigned delay; + lockdep_assert_held_once(&host->lock); + writel(val, host->ioaddr + reg); + + delay = ((mmc_debug >> 24) & 0xf) << ((mmc_debug >> 28) & 0xf); + if (delay) + udelay(delay); +} + +static inline u32 bcm2835_mmc_readl(struct bcm2835_host *host, int reg) +{ + lockdep_assert_held_once(&host->lock); + return readl(host->ioaddr + reg); +} + +static inline void bcm2835_mmc_writew(struct bcm2835_host *host, u16 val, int reg) +{ + u32 oldval = (reg == SDHCI_COMMAND) ? host->shadow : + bcm2835_mmc_readl(host, reg & ~3); + u32 word_num = (reg >> 1) & 1; + u32 word_shift = word_num * 16; + u32 mask = 0xffff << word_shift; + u32 newval = (oldval & ~mask) | (val << word_shift); + + if (reg == SDHCI_TRANSFER_MODE) + host->shadow = newval; + else + bcm2835_mmc_writel(host, newval, reg & ~3, 0); + +} + +static inline void bcm2835_mmc_writeb(struct bcm2835_host *host, u8 val, int reg) +{ + u32 oldval = bcm2835_mmc_readl(host, reg & ~3); + u32 byte_num = reg & 3; + u32 byte_shift = byte_num * 8; + u32 mask = 0xff << byte_shift; + u32 newval = (oldval & ~mask) | (val << byte_shift); + + bcm2835_mmc_writel(host, newval, reg & ~3, 1); +} + + +static inline u16 bcm2835_mmc_readw(struct bcm2835_host *host, int reg) +{ + u32 val = bcm2835_mmc_readl(host, (reg & ~3)); + u32 word_num = (reg >> 1) & 1; + u32 word_shift = word_num * 16; + u32 word = (val >> word_shift) & 0xffff; + + return word; +} + +static inline u8 bcm2835_mmc_readb(struct bcm2835_host *host, int reg) +{ + u32 val = bcm2835_mmc_readl(host, (reg & ~3)); + u32 byte_num = reg & 3; + u32 byte_shift = byte_num * 8; + u32 byte = (val >> byte_shift) & 0xff; + + return byte; +} + +static void bcm2835_mmc_unsignal_irqs(struct bcm2835_host *host, u32 clear) +{ + u32 ier; + + ier = bcm2835_mmc_readl(host, SDHCI_SIGNAL_ENABLE); + ier &= ~clear; + /* change which requests generate IRQs - makes no difference to + the content of SDHCI_INT_STATUS, or the need to acknowledge IRQs */ + bcm2835_mmc_writel(host, ier, SDHCI_SIGNAL_ENABLE, 2); +} + + +static void bcm2835_mmc_dumpregs(struct bcm2835_host *host) +{ + pr_debug(DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n", + mmc_hostname(host->mmc)); + + pr_debug(DRIVER_NAME ": Sys addr: 0x%08x | Version: 0x%08x\n", + bcm2835_mmc_readl(host, SDHCI_DMA_ADDRESS), + bcm2835_mmc_readw(host, SDHCI_HOST_VERSION)); + pr_debug(DRIVER_NAME ": Blk size: 0x%08x | Blk cnt: 0x%08x\n", + bcm2835_mmc_readw(host, SDHCI_BLOCK_SIZE), + bcm2835_mmc_readw(host, SDHCI_BLOCK_COUNT)); + pr_debug(DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n", + bcm2835_mmc_readl(host, SDHCI_ARGUMENT), + bcm2835_mmc_readw(host, SDHCI_TRANSFER_MODE)); + pr_debug(DRIVER_NAME ": Present: 0x%08x | Host ctl: 0x%08x\n", + bcm2835_mmc_readl(host, SDHCI_PRESENT_STATE), + bcm2835_mmc_readb(host, SDHCI_HOST_CONTROL)); + pr_debug(DRIVER_NAME ": Power: 0x%08x | Blk gap: 0x%08x\n", + bcm2835_mmc_readb(host, SDHCI_POWER_CONTROL), + bcm2835_mmc_readb(host, SDHCI_BLOCK_GAP_CONTROL)); + pr_debug(DRIVER_NAME ": Wake-up: 0x%08x | Clock: 0x%08x\n", + bcm2835_mmc_readb(host, SDHCI_WAKE_UP_CONTROL), + bcm2835_mmc_readw(host, SDHCI_CLOCK_CONTROL)); + pr_debug(DRIVER_NAME ": Timeout: 0x%08x | Int stat: 0x%08x\n", + bcm2835_mmc_readb(host, SDHCI_TIMEOUT_CONTROL), + bcm2835_mmc_readl(host, SDHCI_INT_STATUS)); + pr_debug(DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n", + bcm2835_mmc_readl(host, SDHCI_INT_ENABLE), + bcm2835_mmc_readl(host, SDHCI_SIGNAL_ENABLE)); + pr_debug(DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n", + bcm2835_mmc_readw(host, SDHCI_AUTO_CMD_STATUS), + bcm2835_mmc_readw(host, SDHCI_SLOT_INT_STATUS)); + pr_debug(DRIVER_NAME ": Caps: 0x%08x | Caps_1: 0x%08x\n", + bcm2835_mmc_readl(host, SDHCI_CAPABILITIES), + bcm2835_mmc_readl(host, SDHCI_CAPABILITIES_1)); + pr_debug(DRIVER_NAME ": Cmd: 0x%08x | Max curr: 0x%08x\n", + bcm2835_mmc_readw(host, SDHCI_COMMAND), + bcm2835_mmc_readl(host, SDHCI_MAX_CURRENT)); + pr_debug(DRIVER_NAME ": Host ctl2: 0x%08x\n", + bcm2835_mmc_readw(host, SDHCI_HOST_CONTROL2)); + + pr_debug(DRIVER_NAME ": ===========================================\n"); +} + + +static void bcm2835_mmc_reset(struct bcm2835_host *host, u8 mask) +{ + unsigned long timeout; + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); + bcm2835_mmc_writeb(host, mask, SDHCI_SOFTWARE_RESET); + + if (mask & SDHCI_RESET_ALL) + host->clock = 0; + + /* Wait max 100 ms */ + timeout = 100; + + /* hw clears the bit when it's done */ + while (bcm2835_mmc_readb(host, SDHCI_SOFTWARE_RESET) & mask) { + if (timeout == 0) { + pr_err("%s: Reset 0x%x never completed.\n", + mmc_hostname(host->mmc), (int)mask); + bcm2835_mmc_dumpregs(host); + return; + } + timeout--; + spin_unlock_irqrestore(&host->lock, flags); + mdelay(1); + spin_lock_irqsave(&host->lock, flags); + } + + if (100-timeout > 10 && 100-timeout > host->max_delay) { + host->max_delay = 100-timeout; + pr_warn("Warning: MMC controller hung for %d ms\n", host->max_delay); + } + spin_unlock_irqrestore(&host->lock, flags); +} + +static void bcm2835_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios); + +static void bcm2835_mmc_init(struct bcm2835_host *host, int soft) +{ + unsigned long flags; + if (soft) + bcm2835_mmc_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA); + else + bcm2835_mmc_reset(host, SDHCI_RESET_ALL); + + host->ier = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | + SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | + SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC | + SDHCI_INT_TIMEOUT | SDHCI_INT_DATA_END | + SDHCI_INT_RESPONSE; + + spin_lock_irqsave(&host->lock, flags); + bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE, 3); + bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE, 3); + spin_unlock_irqrestore(&host->lock, flags); + + if (soft) { + /* force clock reconfiguration */ + host->clock = 0; + bcm2835_mmc_set_ios(host->mmc, &host->mmc->ios); + } +} + + + +static void bcm2835_mmc_finish_data(struct bcm2835_host *host); + +static void bcm2835_mmc_dma_complete(void *param) +{ + struct bcm2835_host *host = param; + struct dma_chan *dma_chan; + unsigned long flags; + u32 dir_data; + + spin_lock_irqsave(&host->lock, flags); + + host->use_dma = false; + + if (host->data) { + dma_chan = host->dma_chan_rxtx; + if (host->data->flags & MMC_DATA_WRITE) + dir_data = DMA_TO_DEVICE; + else + dir_data = DMA_FROM_DEVICE; + dma_unmap_sg(dma_chan->device->dev, + host->data->sg, host->data->sg_len, + dir_data); + if (! (host->data->flags & MMC_DATA_WRITE)) + bcm2835_mmc_finish_data(host); + } else if (host->wait_for_dma) { + host->wait_for_dma = false; + tasklet_schedule(&host->finish_tasklet); + } + + spin_unlock_irqrestore(&host->lock, flags); +} + +static void bcm2835_bcm2835_mmc_read_block_pio(struct bcm2835_host *host) +{ + unsigned long flags; + size_t blksize, len, chunk; + + u32 scratch = 0; + u8 *buf; + + blksize = host->data->blksz; + chunk = 0; + + local_irq_save(flags); + + while (blksize) { + if (!sg_miter_next(&host->sg_miter)) + BUG(); + + len = min(host->sg_miter.length, blksize); + + blksize -= len; + host->sg_miter.consumed = len; + + buf = host->sg_miter.addr; + + while (len) { + if (chunk == 0) { + scratch = bcm2835_mmc_readl(host, SDHCI_BUFFER); + chunk = 4; + } + + *buf = scratch & 0xFF; + + buf++; + scratch >>= 8; + chunk--; + len--; + } + } + + sg_miter_stop(&host->sg_miter); + + local_irq_restore(flags); +} + +static void bcm2835_bcm2835_mmc_write_block_pio(struct bcm2835_host *host) +{ + unsigned long flags; + size_t blksize, len, chunk; + u32 scratch; + u8 *buf; + + blksize = host->data->blksz; + chunk = 0; + chunk = 0; + scratch = 0; + + local_irq_save(flags); + + while (blksize) { + if (!sg_miter_next(&host->sg_miter)) + BUG(); + + len = min(host->sg_miter.length, blksize); + + blksize -= len; + host->sg_miter.consumed = len; + + buf = host->sg_miter.addr; + + while (len) { + scratch |= (u32)*buf << (chunk * 8); + + buf++; + chunk++; + len--; + + if ((chunk == 4) || ((len == 0) && (blksize == 0))) { + mmc_raw_writel(host, scratch, SDHCI_BUFFER); + chunk = 0; + scratch = 0; + } + } + } + + sg_miter_stop(&host->sg_miter); + + local_irq_restore(flags); +} + + +static void bcm2835_mmc_transfer_pio(struct bcm2835_host *host) +{ + u32 mask; + + BUG_ON(!host->data); + + if (host->blocks == 0) + return; + + if (host->data->flags & MMC_DATA_READ) + mask = SDHCI_DATA_AVAILABLE; + else + mask = SDHCI_SPACE_AVAILABLE; + + while (bcm2835_mmc_readl(host, SDHCI_PRESENT_STATE) & mask) { + + if (host->data->flags & MMC_DATA_READ) + bcm2835_bcm2835_mmc_read_block_pio(host); + else + bcm2835_bcm2835_mmc_write_block_pio(host); + + host->blocks--; + + /* QUIRK used in sdhci.c removes the 'if' */ + /* but it seems this is unnecessary */ + if (host->blocks == 0) + break; + + + } +} + + +static void bcm2835_mmc_transfer_dma(struct bcm2835_host *host) +{ + u32 len, dir_data, dir_slave; + struct dma_async_tx_descriptor *desc = NULL; + struct dma_chan *dma_chan; + + + WARN_ON(!host->data); + + if (!host->data) + return; + + if (host->blocks == 0) + return; + + dma_chan = host->dma_chan_rxtx; + if (host->data->flags & MMC_DATA_READ) { + dir_data = DMA_FROM_DEVICE; + dir_slave = DMA_DEV_TO_MEM; + } else { + dir_data = DMA_TO_DEVICE; + dir_slave = DMA_MEM_TO_DEV; + } + + /* The parameters have already been validated, so this will not fail */ + (void)dmaengine_slave_config(dma_chan, + (dir_data == DMA_FROM_DEVICE) ? + &host->dma_cfg_rx : + &host->dma_cfg_tx); + + BUG_ON(!dma_chan->device); + BUG_ON(!dma_chan->device->dev); + BUG_ON(!host->data->sg); + + len = dma_map_sg(dma_chan->device->dev, host->data->sg, + host->data->sg_len, dir_data); + if (len > 0) { + desc = dmaengine_prep_slave_sg(dma_chan, host->data->sg, + len, dir_slave, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + } else { + dev_err(mmc_dev(host->mmc), "dma_map_sg returned zero length\n"); + } + if (desc) { + unsigned long flags; + spin_lock_irqsave(&host->lock, flags); + bcm2835_mmc_unsignal_irqs(host, SDHCI_INT_DATA_AVAIL | + SDHCI_INT_SPACE_AVAIL); + host->tx_desc = desc; + desc->callback = bcm2835_mmc_dma_complete; + desc->callback_param = host; + spin_unlock_irqrestore(&host->lock, flags); + dmaengine_submit(desc); + dma_async_issue_pending(dma_chan); + } else { + dma_unmap_sg(dma_chan->device->dev, host->data->sg, len, dir_data); + } + +} + + + +static void bcm2835_mmc_set_transfer_irqs(struct bcm2835_host *host) +{ + u32 pio_irqs = SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL; + u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR; + + if (host->use_dma) + host->ier = (host->ier & ~pio_irqs) | dma_irqs; + else + host->ier = (host->ier & ~dma_irqs) | pio_irqs; + + bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE, 4); + bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE, 4); +} + + +static void bcm2835_mmc_prepare_data(struct bcm2835_host *host, struct mmc_command *cmd) +{ + u8 count; + struct mmc_data *data = cmd->data; + + WARN_ON(host->data); + + if (data || (cmd->flags & MMC_RSP_BUSY)) { + count = TIMEOUT_VAL; + bcm2835_mmc_writeb(host, count, SDHCI_TIMEOUT_CONTROL); + } + + if (!data) + return; + + /* Sanity checks */ + BUG_ON(data->blksz * data->blocks > 524288); + BUG_ON(data->blksz > host->mmc->max_blk_size); + BUG_ON(data->blocks > 65535); + + host->data = data; + host->data_early = 0; + host->data->bytes_xfered = 0; + + + if (!(host->flags & SDHCI_REQ_USE_DMA)) { + int flags; + + flags = SG_MITER_ATOMIC; + if (host->data->flags & MMC_DATA_READ) + flags |= SG_MITER_TO_SG; + else + flags |= SG_MITER_FROM_SG; + sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); + host->blocks = data->blocks; + } + + host->use_dma = host->have_dma && data->blocks > PIO_DMA_BARRIER; + + bcm2835_mmc_set_transfer_irqs(host); + + /* Set the DMA boundary value and block size */ + bcm2835_mmc_writew(host, SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG, + data->blksz), SDHCI_BLOCK_SIZE); + bcm2835_mmc_writew(host, data->blocks, SDHCI_BLOCK_COUNT); + + BUG_ON(!host->data); +} + +static void bcm2835_mmc_set_transfer_mode(struct bcm2835_host *host, + struct mmc_command *cmd) +{ + u16 mode; + struct mmc_data *data = cmd->data; + + if (data == NULL) { + /* clear Auto CMD settings for no data CMDs */ + mode = bcm2835_mmc_readw(host, SDHCI_TRANSFER_MODE); + bcm2835_mmc_writew(host, mode & ~(SDHCI_TRNS_AUTO_CMD12 | + SDHCI_TRNS_AUTO_CMD23), SDHCI_TRANSFER_MODE); + return; + } + + WARN_ON(!host->data); + + mode = SDHCI_TRNS_BLK_CNT_EN; + + if ((mmc_op_multi(cmd->opcode) || data->blocks > 1)) { + mode |= SDHCI_TRNS_MULTI; + + /* + * If we are sending CMD23, CMD12 never gets sent + * on successful completion (so no Auto-CMD12). + */ + if (!host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD12)) + mode |= SDHCI_TRNS_AUTO_CMD12; + else if (host->mrq->sbc && (host->flags & SDHCI_AUTO_CMD23)) { + mode |= SDHCI_TRNS_AUTO_CMD23; + bcm2835_mmc_writel(host, host->mrq->sbc->arg, SDHCI_ARGUMENT2, 5); + } + } + + if (data->flags & MMC_DATA_READ) + mode |= SDHCI_TRNS_READ; + if (host->flags & SDHCI_REQ_USE_DMA) + mode |= SDHCI_TRNS_DMA; + + bcm2835_mmc_writew(host, mode, SDHCI_TRANSFER_MODE); +} + +static void bcm2835_mmc_send_command(struct bcm2835_host *host, struct mmc_command *cmd) +{ + int flags; + u32 mask; + unsigned long timeout; + + WARN_ON(host->cmd); + + /* Wait max 10 ms */ + timeout = 1000; + + mask = SDHCI_CMD_INHIBIT; + if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY)) + mask |= SDHCI_DATA_INHIBIT; + + /* We shouldn't wait for data inihibit for stop commands, even + though they might use busy signaling */ + if (host->mrq->data && (cmd == host->mrq->data->stop)) + mask &= ~SDHCI_DATA_INHIBIT; + + while (bcm2835_mmc_readl(host, SDHCI_PRESENT_STATE) & mask) { + if (timeout == 0) { + pr_err("%s: Controller never released inhibit bit(s).\n", + mmc_hostname(host->mmc)); + bcm2835_mmc_dumpregs(host); + cmd->error = -EIO; + tasklet_schedule(&host->finish_tasklet); + return; + } + timeout--; + udelay(10); + } + + if ((1000-timeout)/100 > 1 && (1000-timeout)/100 > host->max_delay) { + host->max_delay = (1000-timeout)/100; + pr_warn("Warning: MMC controller hung for %d ms\n", host->max_delay); + } + + timeout = jiffies; + if (!cmd->data && cmd->busy_timeout > 9000) + timeout += DIV_ROUND_UP(cmd->busy_timeout, 1000) * HZ + HZ; + else + timeout += 10 * HZ; + mod_timer(&host->timer, timeout); + + host->cmd = cmd; + host->use_dma = false; + + bcm2835_mmc_prepare_data(host, cmd); + + bcm2835_mmc_writel(host, cmd->arg, SDHCI_ARGUMENT, 6); + + bcm2835_mmc_set_transfer_mode(host, cmd); + + if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) { + pr_err("%s: Unsupported response type!\n", + mmc_hostname(host->mmc)); + cmd->error = -EINVAL; + tasklet_schedule(&host->finish_tasklet); + return; + } + + if (!(cmd->flags & MMC_RSP_PRESENT)) + flags = SDHCI_CMD_RESP_NONE; + else if (cmd->flags & MMC_RSP_136) + flags = SDHCI_CMD_RESP_LONG; + else if (cmd->flags & MMC_RSP_BUSY) + flags = SDHCI_CMD_RESP_SHORT_BUSY; + else + flags = SDHCI_CMD_RESP_SHORT; + + if (cmd->flags & MMC_RSP_CRC) + flags |= SDHCI_CMD_CRC; + if (cmd->flags & MMC_RSP_OPCODE) + flags |= SDHCI_CMD_INDEX; + + if (cmd->data) + flags |= SDHCI_CMD_DATA; + + bcm2835_mmc_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); +} + + +static void bcm2835_mmc_finish_data(struct bcm2835_host *host) +{ + struct mmc_data *data; + + BUG_ON(!host->data); + + data = host->data; + host->data = NULL; + + if (data->error) + data->bytes_xfered = 0; + else + data->bytes_xfered = data->blksz * data->blocks; + + /* + * Need to send CMD12 if - + * a) open-ended multiblock transfer (no CMD23) + * b) error in multiblock transfer + */ + if (data->stop && + (data->error || + !host->mrq->sbc)) { + + /* + * The controller needs a reset of internal state machines + * upon error conditions. + */ + if (data->error) { + bcm2835_mmc_reset(host, SDHCI_RESET_CMD); + bcm2835_mmc_reset(host, SDHCI_RESET_DATA); + } + + bcm2835_mmc_send_command(host, data->stop); + } else if (host->use_dma) { + host->wait_for_dma = true; + } else { + tasklet_schedule(&host->finish_tasklet); + } +} + +static void bcm2835_mmc_finish_command(struct bcm2835_host *host) +{ + int i; + + BUG_ON(host->cmd == NULL); + + if (host->cmd->flags & MMC_RSP_PRESENT) { + if (host->cmd->flags & MMC_RSP_136) { + /* CRC is stripped so we need to do some shifting. */ + for (i = 0; i < 4; i++) { + host->cmd->resp[i] = bcm2835_mmc_readl(host, + SDHCI_RESPONSE + (3-i)*4) << 8; + if (i != 3) + host->cmd->resp[i] |= + bcm2835_mmc_readb(host, + SDHCI_RESPONSE + (3-i)*4-1); + } + } else { + host->cmd->resp[0] = bcm2835_mmc_readl(host, SDHCI_RESPONSE); + } + } + + host->cmd->error = 0; + + /* Finished CMD23, now send actual command. */ + if (host->cmd == host->mrq->sbc) { + host->cmd = NULL; + bcm2835_mmc_send_command(host, host->mrq->cmd); + + if (host->mrq->cmd->data && host->use_dma) { + /* DMA transfer starts now, PIO starts after interrupt */ + bcm2835_mmc_transfer_dma(host); + } + } else { + + /* Processed actual command. */ + if (host->data && host->data_early) + bcm2835_mmc_finish_data(host); + + if (!host->cmd->data) + tasklet_schedule(&host->finish_tasklet); + + host->cmd = NULL; + } +} + + +static void bcm2835_mmc_timeout_timer(struct timer_list *t) +{ + struct bcm2835_host *host = timer_container_of(host, t, timer); + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); + + if (host->mrq) { + pr_err("%s: Timeout waiting for hardware interrupt.\n", + mmc_hostname(host->mmc)); + bcm2835_mmc_dumpregs(host); + + if (host->data) { + host->data->error = -ETIMEDOUT; + bcm2835_mmc_finish_data(host); + } else { + if (host->cmd) + host->cmd->error = -ETIMEDOUT; + else + host->mrq->cmd->error = -ETIMEDOUT; + + tasklet_schedule(&host->finish_tasklet); + } + } + + spin_unlock_irqrestore(&host->lock, flags); +} + + +static void bcm2835_mmc_enable_sdio_irq_nolock(struct bcm2835_host *host, int enable) +{ + if (!(host->flags & SDHCI_DEVICE_DEAD)) { + if (enable) + host->ier |= SDHCI_INT_CARD_INT; + else + host->ier &= ~SDHCI_INT_CARD_INT; + + bcm2835_mmc_writel(host, host->ier, SDHCI_INT_ENABLE, 7); + bcm2835_mmc_writel(host, host->ier, SDHCI_SIGNAL_ENABLE, 7); + } +} + +static void bcm2835_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) +{ + struct bcm2835_host *host = mmc_priv(mmc); + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); + if (enable) + host->flags |= SDHCI_SDIO_IRQ_ENABLED; + else + host->flags &= ~SDHCI_SDIO_IRQ_ENABLED; + + bcm2835_mmc_enable_sdio_irq_nolock(host, enable); + spin_unlock_irqrestore(&host->lock, flags); +} + +static void bcm2835_mmc_cmd_irq(struct bcm2835_host *host, u32 intmask) +{ + + BUG_ON(intmask == 0); + + if (!host->cmd) { + pr_err("%s: Got command interrupt 0x%08x even " + "though no command operation was in progress.\n", + mmc_hostname(host->mmc), (unsigned)intmask); + bcm2835_mmc_dumpregs(host); + return; + } + + if (intmask & SDHCI_INT_TIMEOUT) + host->cmd->error = -ETIMEDOUT; + else if (intmask & (SDHCI_INT_CRC | SDHCI_INT_END_BIT | + SDHCI_INT_INDEX)) { + host->cmd->error = -EILSEQ; + } + + if (host->cmd->error) { + tasklet_schedule(&host->finish_tasklet); + return; + } + + if (intmask & SDHCI_INT_RESPONSE) + bcm2835_mmc_finish_command(host); + +} + +static void bcm2835_mmc_data_irq(struct bcm2835_host *host, u32 intmask) +{ + struct dma_chan *dma_chan; + u32 dir_data; + + BUG_ON(intmask == 0); + + if (!host->data) { + /* + * The "data complete" interrupt is also used to + * indicate that a busy state has ended. See comment + * above in sdhci_cmd_irq(). + */ + if (host->cmd && (host->cmd->flags & MMC_RSP_BUSY)) { + if (intmask & SDHCI_INT_DATA_END) { + bcm2835_mmc_finish_command(host); + return; + } + } + + pr_debug("%s: Got data interrupt 0x%08x even " + "though no data operation was in progress.\n", + mmc_hostname(host->mmc), (unsigned)intmask); + bcm2835_mmc_dumpregs(host); + + return; + } + + if (intmask & SDHCI_INT_DATA_TIMEOUT) + host->data->error = -ETIMEDOUT; + else if (intmask & SDHCI_INT_DATA_END_BIT) + host->data->error = -EILSEQ; + else if ((intmask & SDHCI_INT_DATA_CRC) && + SDHCI_GET_CMD(bcm2835_mmc_readw(host, SDHCI_COMMAND)) + != MMC_BUS_TEST_R) + host->data->error = -EILSEQ; + + if (host->use_dma) { + if (host->data->flags & MMC_DATA_WRITE) { + /* IRQ handled here */ + + dma_chan = host->dma_chan_rxtx; + dir_data = DMA_TO_DEVICE; + dma_unmap_sg(dma_chan->device->dev, + host->data->sg, host->data->sg_len, + dir_data); + + bcm2835_mmc_finish_data(host); + } + + } else { + if (host->data->error) + bcm2835_mmc_finish_data(host); + else { + if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)) + bcm2835_mmc_transfer_pio(host); + + if (intmask & SDHCI_INT_DATA_END) { + if (host->cmd) { + /* + * Data managed to finish before the + * command completed. Make sure we do + * things in the proper order. + */ + host->data_early = 1; + } else { + bcm2835_mmc_finish_data(host); + } + } + } + } +} + + +static irqreturn_t bcm2835_mmc_irq(int irq, void *dev_id) +{ + irqreturn_t result = IRQ_NONE; + struct bcm2835_host *host = dev_id; + u32 intmask, mask, unexpected = 0; + int max_loops = 16; + + spin_lock(&host->lock); + + intmask = bcm2835_mmc_readl(host, SDHCI_INT_STATUS); + + if (!intmask || intmask == 0xffffffff) { + result = IRQ_NONE; + goto out; + } + + do { + /* Clear selected interrupts. */ + mask = intmask & (SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | + SDHCI_INT_BUS_POWER); + bcm2835_mmc_writel(host, mask, SDHCI_INT_STATUS, 8); + + + if (intmask & SDHCI_INT_CMD_MASK) + bcm2835_mmc_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK); + + if (intmask & SDHCI_INT_DATA_MASK) + bcm2835_mmc_data_irq(host, intmask & SDHCI_INT_DATA_MASK); + + if (intmask & SDHCI_INT_BUS_POWER) + pr_err("%s: Card is consuming too much power!\n", + mmc_hostname(host->mmc)); + + if (intmask & SDHCI_INT_CARD_INT) { + bcm2835_mmc_enable_sdio_irq_nolock(host, false); + sdio_signal_irq(host->mmc); + } + + intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE | + SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | + SDHCI_INT_ERROR | SDHCI_INT_BUS_POWER | + SDHCI_INT_CARD_INT); + + if (intmask) { + unexpected |= intmask; + bcm2835_mmc_writel(host, intmask, SDHCI_INT_STATUS, 9); + } + + if (result == IRQ_NONE) + result = IRQ_HANDLED; + + intmask = bcm2835_mmc_readl(host, SDHCI_INT_STATUS); + } while (intmask && --max_loops); +out: + spin_unlock(&host->lock); + + if (unexpected) { + pr_err("%s: Unexpected interrupt 0x%08x.\n", + mmc_hostname(host->mmc), unexpected); + bcm2835_mmc_dumpregs(host); + } + + return result; +} + + +static void bcm2835_mmc_ack_sdio_irq(struct mmc_host *mmc) +{ + struct bcm2835_host *host = mmc_priv(mmc); + unsigned long flags; + + spin_lock_irqsave(&host->lock, flags); + if (host->flags & SDHCI_SDIO_IRQ_ENABLED) + bcm2835_mmc_enable_sdio_irq_nolock(host, true); + spin_unlock_irqrestore(&host->lock, flags); +} + +static void bcm2835_mmc_set_clock(struct bcm2835_host *host, unsigned int clock) +{ + int div = 0; /* Initialized for compiler warning */ + int real_div = div, clk_mul = 1; + u16 clk = 0; + unsigned long timeout; + unsigned int input_clock = clock; + + if (host->overclock_50 && (clock == 50000000)) + clock = host->overclock_50 * 1000000 + 999999; + + host->mmc->actual_clock = 0; + + bcm2835_mmc_writew(host, 0, SDHCI_CLOCK_CONTROL); + + if (clock == 0) + return; + + /* Version 3.00 divisors must be a multiple of 2. */ + if (host->max_clk <= clock) + div = 1; + else { + for (div = 2; div < SDHCI_MAX_DIV_SPEC_300; + div += 2) { + if ((host->max_clk / div) <= clock) + break; + } + } + + real_div = div; + div >>= 1; + + if (real_div) + clock = (host->max_clk * clk_mul) / real_div; + host->mmc->actual_clock = clock; + + if ((clock > input_clock) && (clock > host->max_overclock)) { + pr_warn("%s: Overclocking to %dHz\n", + mmc_hostname(host->mmc), clock); + host->max_overclock = clock; + } + + clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; + clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) + << SDHCI_DIVIDER_HI_SHIFT; + clk |= SDHCI_CLOCK_INT_EN; + bcm2835_mmc_writew(host, clk, SDHCI_CLOCK_CONTROL); + + /* Wait max 20 ms */ + timeout = 20; + while (!((clk = bcm2835_mmc_readw(host, SDHCI_CLOCK_CONTROL)) + & SDHCI_CLOCK_INT_STABLE)) { + if (timeout == 0) { + pr_err("%s: Internal clock never " + "stabilised.\n", mmc_hostname(host->mmc)); + bcm2835_mmc_dumpregs(host); + return; + } + timeout--; + mdelay(1); + } + + if (20-timeout > 10 && 20-timeout > host->max_delay) { + host->max_delay = 20-timeout; + pr_warn("Warning: MMC controller hung for %d ms\n", host->max_delay); + } + + clk |= SDHCI_CLOCK_CARD_EN; + bcm2835_mmc_writew(host, clk, SDHCI_CLOCK_CONTROL); +} + +static void bcm2835_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) +{ + struct bcm2835_host *host; + unsigned long flags; + + host = mmc_priv(mmc); + + spin_lock_irqsave(&host->lock, flags); + + WARN_ON(host->mrq != NULL); + + host->mrq = mrq; + + if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23)) + bcm2835_mmc_send_command(host, mrq->sbc); + else + bcm2835_mmc_send_command(host, mrq->cmd); + + spin_unlock_irqrestore(&host->lock, flags); + + if (!(mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23)) && mrq->cmd->data && host->use_dma) { + /* DMA transfer starts now, PIO starts after interrupt */ + bcm2835_mmc_transfer_dma(host); + } +} + + +static void bcm2835_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +{ + + struct bcm2835_host *host = mmc_priv(mmc); + unsigned long flags; + u8 ctrl; + u16 clk, ctrl_2; + + pr_debug("bcm2835_mmc_set_ios: clock %d, pwr %d, bus_width %d, timing %d, vdd %d, drv_type %d\n", + ios->clock, ios->power_mode, ios->bus_width, + ios->timing, ios->signal_voltage, ios->drv_type); + + spin_lock_irqsave(&host->lock, flags); + + if (!ios->clock || ios->clock != host->clock) { + bcm2835_mmc_set_clock(host, ios->clock); + host->clock = ios->clock; + } + + if (host->pwr != SDHCI_POWER_330) { + host->pwr = SDHCI_POWER_330; + bcm2835_mmc_writeb(host, SDHCI_POWER_330 | SDHCI_POWER_ON, SDHCI_POWER_CONTROL); + } + + ctrl = bcm2835_mmc_readb(host, SDHCI_HOST_CONTROL); + + /* set bus width */ + ctrl &= ~SDHCI_CTRL_8BITBUS; + if (ios->bus_width == MMC_BUS_WIDTH_4) + ctrl |= SDHCI_CTRL_4BITBUS; + else + ctrl &= ~SDHCI_CTRL_4BITBUS; + + ctrl &= ~SDHCI_CTRL_HISPD; /* NO_HISPD_BIT */ + + + bcm2835_mmc_writeb(host, ctrl, SDHCI_HOST_CONTROL); + /* + * We only need to set Driver Strength if the + * preset value enable is not set. + */ + ctrl_2 = bcm2835_mmc_readw(host, SDHCI_HOST_CONTROL2); + ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK; + if (ios->drv_type == MMC_SET_DRIVER_TYPE_A) + ctrl_2 |= SDHCI_CTRL_DRV_TYPE_A; + else if (ios->drv_type == MMC_SET_DRIVER_TYPE_C) + ctrl_2 |= SDHCI_CTRL_DRV_TYPE_C; + + bcm2835_mmc_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); + + /* Reset SD Clock Enable */ + clk = bcm2835_mmc_readw(host, SDHCI_CLOCK_CONTROL); + clk &= ~SDHCI_CLOCK_CARD_EN; + bcm2835_mmc_writew(host, clk, SDHCI_CLOCK_CONTROL); + + /* Re-enable SD Clock */ + bcm2835_mmc_set_clock(host, host->clock); + bcm2835_mmc_writeb(host, ctrl, SDHCI_HOST_CONTROL); + + spin_unlock_irqrestore(&host->lock, flags); +} + + +static struct mmc_host_ops bcm2835_ops = { + .request = bcm2835_mmc_request, + .set_ios = bcm2835_mmc_set_ios, + .enable_sdio_irq = bcm2835_mmc_enable_sdio_irq, + .ack_sdio_irq = bcm2835_mmc_ack_sdio_irq, +}; + + +static void bcm2835_mmc_tasklet_finish(unsigned long param) +{ + struct bcm2835_host *host; + unsigned long flags; + struct mmc_request *mrq; + + host = (struct bcm2835_host *)param; + + spin_lock_irqsave(&host->lock, flags); + + /* + * If this tasklet gets rescheduled while running, it will + * be run again afterwards but without any active request. + */ + if (!host->mrq) { + spin_unlock_irqrestore(&host->lock, flags); + return; + } + + timer_delete(&host->timer); + + mrq = host->mrq; + + /* + * The controller needs a reset of internal state machines + * upon error conditions. + */ + if (!(host->flags & SDHCI_DEVICE_DEAD) && + ((mrq->cmd && mrq->cmd->error) || + (mrq->data && (mrq->data->error || + (mrq->data->stop && mrq->data->stop->error))))) { + + spin_unlock_irqrestore(&host->lock, flags); + bcm2835_mmc_reset(host, SDHCI_RESET_CMD); + bcm2835_mmc_reset(host, SDHCI_RESET_DATA); + spin_lock_irqsave(&host->lock, flags); + } + + host->mrq = NULL; + host->cmd = NULL; + host->data = NULL; + + spin_unlock_irqrestore(&host->lock, flags); + mmc_request_done(host->mmc, mrq); +} + + + +static int bcm2835_mmc_add_host(struct bcm2835_host *host) +{ + struct mmc_host *mmc = host->mmc; + struct device *dev = mmc->parent; +#ifndef FORCE_PIO + struct dma_slave_config cfg; +#endif + int ret; + + bcm2835_mmc_reset(host, SDHCI_RESET_ALL); + + host->clk_mul = 0; + + if (!mmc->f_max || mmc->f_max > host->max_clk) + mmc->f_max = host->max_clk; + mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300; + + /* SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK */ + host->timeout_clk = mmc->f_max / 1000; + mmc->max_busy_timeout = (1 << 27) / host->timeout_clk; + + /* host controller capabilities */ + mmc->caps |= MMC_CAP_CMD23 | MMC_CAP_NEEDS_POLL | + MMC_CAP_SDIO_IRQ | MMC_CAP_SD_HIGHSPEED | + MMC_CAP_MMC_HIGHSPEED; + + mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD; + + host->flags = SDHCI_AUTO_CMD23; + + dev_info(dev, "mmc_debug:%x mmc_debug2:%x\n", mmc_debug, mmc_debug2); +#ifdef FORCE_PIO + dev_info(dev, "Forcing PIO mode\n"); + host->have_dma = false; +#else + if (IS_ERR_OR_NULL(host->dma_chan_rxtx)) { + dev_err(dev, "%s: Unable to initialise DMA channel. Falling back to PIO\n", + DRIVER_NAME); + host->have_dma = false; + } else { + dev_info(dev, "DMA channel allocated"); + + cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + + /* Validate the slave configurations */ + + cfg.direction = DMA_MEM_TO_DEV; + cfg.src_addr = 0; + cfg.dst_addr = host->bus_addr + SDHCI_BUFFER; + + ret = dmaengine_slave_config(host->dma_chan_rxtx, &cfg); + + if (ret == 0) { + host->dma_cfg_tx = cfg; + + cfg.direction = DMA_DEV_TO_MEM; + cfg.src_addr = host->bus_addr + SDHCI_BUFFER; + cfg.dst_addr = 0; + + ret = dmaengine_slave_config(host->dma_chan_rxtx, &cfg); + } + + if (ret == 0) { + host->dma_cfg_rx = cfg; + + host->have_dma = true; + } else { + pr_err("%s: unable to configure DMA channel. " + "Falling back to PIO\n", + mmc_hostname(mmc)); + dma_release_channel(host->dma_chan_rxtx); + host->dma_chan_rxtx = NULL; + host->have_dma = false; + } + } +#endif + mmc->max_segs = 128; + mmc->max_req_size = min_t(size_t, 524288, dma_max_mapping_size(dev)); + mmc->max_seg_size = mmc->max_req_size; + mmc->max_blk_size = 512; + mmc->max_blk_count = 65535; + + /* report supported voltage ranges */ + mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; + + tasklet_init(&host->finish_tasklet, + bcm2835_mmc_tasklet_finish, (unsigned long)host); + + timer_setup(&host->timer, bcm2835_mmc_timeout_timer, 0); + init_waitqueue_head(&host->buf_ready_int); + + bcm2835_mmc_init(host, 0); + ret = request_irq(host->irq, bcm2835_mmc_irq, IRQF_SHARED, + mmc_hostname(mmc), host); + if (ret) { + dev_err(dev, "Failed to request IRQ %d: %d\n", host->irq, ret); + goto untasklet; + } + + ret = mmc_add_host(mmc); + if (ret) { + dev_err(dev, "could not add MMC host\n"); + goto free_irq; + } + + return 0; + +free_irq: + free_irq(host->irq, host); +untasklet: + tasklet_kill(&host->finish_tasklet); + + return ret; +} + +static int bcm2835_mmc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->of_node; + struct clk *clk; + struct resource *iomem; + struct bcm2835_host *host; + struct mmc_host *mmc; + int ret; + + mmc = mmc_alloc_host(sizeof(*host), dev); + if (!mmc) + return -ENOMEM; + + mmc->ops = &bcm2835_ops; + host = mmc_priv(mmc); + host->mmc = mmc; + host->timeout = msecs_to_jiffies(1000); + spin_lock_init(&host->lock); + + host->ioaddr = devm_platform_get_and_ioremap_resource(pdev, 0, &iomem); + if (IS_ERR(host->ioaddr)) { + ret = PTR_ERR(host->ioaddr); + goto err; + } + + host->bus_addr = iomem->start; + +#ifndef FORCE_PIO + if (node) { + host->dma_chan_rxtx = dma_request_slave_channel(dev, "rx-tx"); + if (!host->dma_chan_rxtx) + host->dma_chan_rxtx = + dma_request_slave_channel(dev, "tx"); + if (!host->dma_chan_rxtx) + host->dma_chan_rxtx = + dma_request_slave_channel(dev, "rx"); + } else { + dma_cap_mask_t mask; + + dma_cap_zero(mask); + /* we don't care about the channel, any would work */ + dma_cap_set(DMA_SLAVE, mask); + host->dma_chan_rxtx = dma_request_channel(mask, NULL, NULL); + } +#endif + clk = devm_clk_get(dev, NULL); + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); + if (ret == -EPROBE_DEFER) + dev_info(dev, "could not get clk, deferring probe\n"); + else + dev_err(dev, "could not get clk\n"); + goto err; + } + + host->max_clk = clk_get_rate(clk); + + host->irq = platform_get_irq(pdev, 0); + if (host->irq <= 0) { + dev_err(dev, "get IRQ failed\n"); + ret = -EINVAL; + goto err; + } + + if (node) { + ret = mmc_of_parse(mmc); + if (ret) + goto err; + + /* Read any custom properties */ + of_property_read_u32(node, + "brcm,overclock-50", + &host->overclock_50); + } else { + mmc->caps |= MMC_CAP_4_BIT_DATA; + } + + ret = bcm2835_mmc_add_host(host); + if (ret) + goto err; + + platform_set_drvdata(pdev, host); + + return 0; +err: + if (host->dma_chan_rxtx) + dma_release_channel(host->dma_chan_rxtx); + mmc_free_host(mmc); + + return ret; +} + +static void bcm2835_mmc_remove(struct platform_device *pdev) +{ + struct bcm2835_host *host = platform_get_drvdata(pdev); + unsigned long flags; + int dead; + u32 scratch; + + dead = 0; + scratch = bcm2835_mmc_readl(host, SDHCI_INT_STATUS); + if (scratch == (u32)-1) + dead = 1; + + + if (dead) { + spin_lock_irqsave(&host->lock, flags); + + host->flags |= SDHCI_DEVICE_DEAD; + + if (host->mrq) { + pr_err("%s: Controller removed during " + " transfer!\n", mmc_hostname(host->mmc)); + + host->mrq->cmd->error = -ENOMEDIUM; + tasklet_schedule(&host->finish_tasklet); + } + + spin_unlock_irqrestore(&host->lock, flags); + } + + mmc_remove_host(host->mmc); + + if (!dead) + bcm2835_mmc_reset(host, SDHCI_RESET_ALL); + + free_irq(host->irq, host); + + timer_delete_sync(&host->timer); + + tasklet_kill(&host->finish_tasklet); + + if (host->dma_chan_rxtx) + dma_release_channel(host->dma_chan_rxtx); + + mmc_free_host(host->mmc); +} + + +static const struct of_device_id bcm2835_mmc_match[] = { + { .compatible = "brcm,bcm2835-mmc" }, + { } +}; +MODULE_DEVICE_TABLE(of, bcm2835_mmc_match); + + + +static struct platform_driver bcm2835_mmc_driver = { + .probe = bcm2835_mmc_probe, + .remove = bcm2835_mmc_remove, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = bcm2835_mmc_match, + }, +}; +module_platform_driver(bcm2835_mmc_driver); + +module_param(mmc_debug, uint, 0644); +module_param(mmc_debug2, uint, 0644); +MODULE_ALIAS("platform:mmc-bcm2835"); +MODULE_DESCRIPTION("BCM2835 SDHCI driver"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Gellert Weisz"); diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c index ee63835b3ca0..bae88c3b45b5 100644 --- a/drivers/mmc/host/bcm2835.c +++ b/drivers/mmc/host/bcm2835.c @@ -38,7 +38,6 @@ #include <linux/io.h> #include <linux/iopoll.h> #include <linux/module.h> -#include <linux/of_address.h> #include <linux/of_irq.h> #include <linux/platform_device.h> #include <linux/scatterlist.h> @@ -1367,8 +1366,8 @@ static int bcm2835_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct bcm2835_host *host; + struct resource *iomem; struct mmc_host *mmc; - const __be32 *regaddr_p; int ret; dev_dbg(dev, "%s\n", __func__); @@ -1381,23 +1380,13 @@ static int bcm2835_probe(struct platform_device *pdev) host->pdev = pdev; spin_lock_init(&host->lock); - host->ioaddr = devm_platform_ioremap_resource(pdev, 0); + host->ioaddr = devm_platform_get_and_ioremap_resource(pdev, 0, &iomem); if (IS_ERR(host->ioaddr)) { ret = PTR_ERR(host->ioaddr); goto err; } - /* Parse OF address directly to get the physical address for - * DMA to our registers. - */ - regaddr_p = of_get_address(pdev->dev.of_node, 0, NULL, NULL); - if (!regaddr_p) { - dev_err(dev, "Can't get phys address\n"); - ret = -EINVAL; - goto err; - } - - host->phys_addr = be32_to_cpup(regaddr_p); + host->phys_addr = iomem->start; host->dma_chan = NULL; host->dma_desc = NULL; diff --git a/drivers/mmc/host/cqhci-core.c b/drivers/mmc/host/cqhci-core.c index 178277d90c31..78e80bc574eb 100644 --- a/drivers/mmc/host/cqhci-core.c +++ b/drivers/mmc/host/cqhci-core.c @@ -388,9 +388,11 @@ static void cqhci_off(struct mmc_host *mmc) err = readx_poll_timeout(cqhci_read_ctl, cq_host, reg, reg & CQHCI_HALT, 0, CQHCI_OFF_TIMEOUT); - if (err < 0) + if (err < 0) { pr_err("%s: cqhci: CQE stuck on\n", mmc_hostname(mmc)); - else + /* eMMC v5.1 B.2.8 recommends writing 0 to CQHCI_CTL if stuck */ + cqhci_writel(cq_host, 0, CQHCI_CTL); + } else pr_debug("%s: cqhci: CQE off\n", mmc_hostname(mmc)); if (cq_host->ops->post_disable) @@ -980,8 +982,11 @@ static bool cqhci_halt(struct mmc_host *mmc, unsigned int timeout) ret = cqhci_halted(cq_host); - if (!ret) + if (!ret) { pr_warn("%s: cqhci: Failed to halt\n", mmc_hostname(mmc)); + /* eMMC v5.1 B.2.8 recommends writing 0 to CQHCI_CTL if stuck */ + cqhci_writel(cq_host, 0, CQHCI_CTL); + } return ret; } diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c index efc2f3bdc631..721e40d5a959 100644 --- a/drivers/mmc/host/sdhci-brcmstb.c +++ b/drivers/mmc/host/sdhci-brcmstb.c @@ -12,6 +12,8 @@ #include <linux/of.h> #include <linux/bitops.h> #include <linux/delay.h> +#include <linux/pinctrl/consumer.h> +#include <linux/regulator/consumer.h> #include "sdhci-cqhci.h" #include "sdhci-pltfm.h" @@ -28,29 +30,38 @@ #define BRCMSTB_PRIV_FLAGS_HAS_CQE BIT(0) #define BRCMSTB_PRIV_FLAGS_GATE_CLOCK BIT(1) +#define BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS BIT(2) #define SDHCI_ARASAN_CQE_BASE_ADDR 0x200 #define SDIO_CFG_CQ_CAPABILITY 0x4c -#define SDIO_CFG_CQ_CAPABILITY_FMUL GENMASK(13, 12) +#define SDIO_CFG_CQ_CAPABILITY_FMUL_SHIFT 12 #define SDIO_CFG_CTRL 0x0 #define SDIO_CFG_CTRL_SDCD_N_TEST_EN BIT(31) #define SDIO_CFG_CTRL_SDCD_N_TEST_LEV BIT(30) +#define SDIO_CFG_SD_PIN_SEL 0x44 +#define SDIO_CFG_SD_PIN_SEL_MASK 0x3 +#define SDIO_CFG_SD_PIN_SEL_SD BIT(1) +#define SDIO_CFG_SD_PIN_SEL_MMC BIT(0) + #define SDIO_CFG_MAX_50MHZ_MODE 0x1ac #define SDIO_CFG_MAX_50MHZ_MODE_STRAP_OVERRIDE BIT(31) #define SDIO_CFG_MAX_50MHZ_MODE_ENABLE BIT(0) -#define MMC_CAP_HSE_MASK (MMC_CAP2_HSX00_1_2V | MMC_CAP2_HSX00_1_8V) -/* Select all SD UHS type I SDR speed above 50MB/s */ -#define MMC_CAP_UHS_I_SDR_MASK (MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104) - struct sdhci_brcmstb_priv { void __iomem *cfg_regs; unsigned int flags; struct clk *base_clk; u32 base_freq_hz; + struct regulator *sde_1v8; + struct device_node *sde_pcie; + void *__iomem sde_ioaddr; + void *__iomem sde_ioaddr2; + struct pinctrl *pinctrl; + struct pinctrl_state *pins_default; + struct pinctrl_state *pins_sdex; }; struct brcmstb_match_priv { @@ -141,6 +152,42 @@ static void sdhci_brcmstb_hs400es(struct mmc_host *mmc, struct mmc_ios *ios) writel(reg, host->ioaddr + SDHCI_VENDOR); } +static void sdhci_bcm2712_set_clock(struct sdhci_host *host, unsigned int clock) +{ + u16 clk; + u32 reg; + bool is_emmc_rate = false; + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host); + + host->mmc->actual_clock = 0; + + sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); + + switch (host->mmc->ios.timing) { + case MMC_TIMING_MMC_HS400: + case MMC_TIMING_MMC_HS200: + case MMC_TIMING_MMC_DDR52: + case MMC_TIMING_MMC_HS: + is_emmc_rate = true; + break; + } + + reg = readl(brcmstb_priv->cfg_regs + SDIO_CFG_SD_PIN_SEL); + reg &= ~SDIO_CFG_SD_PIN_SEL_MASK; + if (is_emmc_rate) + reg |= SDIO_CFG_SD_PIN_SEL_MMC; + else + reg |= SDIO_CFG_SD_PIN_SEL_SD; + writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_SD_PIN_SEL); + + if (clock == 0) + return; + + clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock); + sdhci_enable_clk(host, clk); +} + static void sdhci_brcmstb_set_clock(struct sdhci_host *host, unsigned int clock) { u16 clk; @@ -156,6 +203,17 @@ static void sdhci_brcmstb_set_clock(struct sdhci_host *host, unsigned int clock) sdhci_enable_clk(host, clk); } +static void sdhci_brcmstb_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); +} + static void sdhci_brcmstb_set_uhs_signaling(struct sdhci_host *host, unsigned int timing) { @@ -185,21 +243,41 @@ static void sdhci_brcmstb_set_uhs_signaling(struct sdhci_host *host, sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); } +static void sdhci_bcm2712_hs400_downgrade(struct mmc_host *mmc) +{ + struct sdhci_host *host = mmc_priv(mmc); + /* + * The eMMC PHY and its internal controller parses and validates + * the uhs_mode, divisor, pin_sel, and sampling clock select + * output from the SD controller. It will refuse to update its + * config if HS timings are selected while the clock is >52MHz. + * so bump the clock down now before card/controller setup is + * performed. + */ + sdhci_bcm2712_set_clock(host, 52000000); +} + static void sdhci_brcmstb_cfginit_2712(struct sdhci_host *host) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host); u32 reg; + u32 uhs_mask = (MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104); + u32 hsemmc_mask = (MMC_CAP2_HS200_1_8V_SDR | MMC_CAP2_HS200_1_2V_SDR | + MMC_CAP2_HS400_1_8V | MMC_CAP2_HS400_1_2V); + u32 base_clk_mhz; /* * If we support a speed that requires tuning, * then select the delay line PHY as the clock source. */ - if ((host->mmc->caps & MMC_CAP_UHS_I_SDR_MASK) || (host->mmc->caps2 & MMC_CAP_HSE_MASK)) { + if ((host->mmc->caps & uhs_mask) || (host->mmc->caps2 & hsemmc_mask)) { reg = readl(brcmstb_priv->cfg_regs + SDIO_CFG_MAX_50MHZ_MODE); reg &= ~SDIO_CFG_MAX_50MHZ_MODE_ENABLE; reg |= SDIO_CFG_MAX_50MHZ_MODE_STRAP_OVERRIDE; writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_MAX_50MHZ_MODE); + + host->mmc_host_ops.hs400_downgrade = sdhci_bcm2712_hs400_downgrade; } if ((host->mmc->caps & MMC_CAP_NONREMOVABLE) || @@ -210,6 +288,109 @@ static void sdhci_brcmstb_cfginit_2712(struct sdhci_host *host) reg |= SDIO_CFG_CTRL_SDCD_N_TEST_EN; writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_CTRL); } + + /* Guesstimate the timer frequency (controller base clock) */ + base_clk_mhz = max_t(u32, clk_get_rate(pltfm_host->clk) / (1000 * 1000), 1); + reg = (3 << SDIO_CFG_CQ_CAPABILITY_FMUL_SHIFT) | base_clk_mhz; + writel(reg, brcmstb_priv->cfg_regs + SDIO_CFG_CQ_CAPABILITY); +} + +static int bcm2712_init_sd_express(struct sdhci_host *host, struct mmc_ios *ios) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct sdhci_brcmstb_priv *brcmstb_priv = sdhci_pltfm_priv(pltfm_host); + struct device *dev = host->mmc->parent; + u32 ctrl_val; + u32 present_state; + int ret; + + if (!brcmstb_priv->sde_ioaddr || !brcmstb_priv->sde_ioaddr2) + return -EINVAL; + + if (!brcmstb_priv->pinctrl) + return -EINVAL; + + /* Turn off the SD clock first */ + sdhci_set_clock(host, 0); + + /* Disable SD DAT0-3 pulls */ + pinctrl_select_state(brcmstb_priv->pinctrl, brcmstb_priv->pins_sdex); + + ctrl_val = readl(brcmstb_priv->sde_ioaddr); + dev_dbg(dev, "ctrl_val 1 %08x\n", ctrl_val); + + /* Tri-state the SD pins */ + ctrl_val |= 0x1ff8; + writel(ctrl_val, brcmstb_priv->sde_ioaddr); + dev_dbg(dev, "ctrl_val 1->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr)); + /* Let voltages settle */ + udelay(100); + + /* Enable the PCIe sideband pins */ + ctrl_val &= ~0x6000; + writel(ctrl_val, brcmstb_priv->sde_ioaddr); + dev_dbg(dev, "ctrl_val 1->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr)); + /* Let voltages settle */ + udelay(100); + + /* Turn on the 1v8 VDD2 regulator */ + ret = regulator_enable(brcmstb_priv->sde_1v8); + if (ret) + return ret; + + /* Wait for Tpvcrl */ + msleep(1); + + /* Sample DAT2 (CLKREQ#) - if low, card is in PCIe mode */ + present_state = sdhci_readl(host, SDHCI_PRESENT_STATE); + present_state = (present_state & SDHCI_DATA_LVL_MASK) >> SDHCI_DATA_LVL_SHIFT; + dev_dbg(dev, "state = 0x%08x\n", present_state); + + if (present_state & BIT(2)) { + dev_err(dev, "DAT2 still high, abandoning SDex switch\n"); + return -ENODEV; + } + + /* Turn on the LCPLL PTEST mux */ + ctrl_val = readl(brcmstb_priv->sde_ioaddr2 + 20); // misc5 + ctrl_val &= ~(0x7 << 7); + ctrl_val |= 3 << 7; + writel(ctrl_val, brcmstb_priv->sde_ioaddr2 + 20); + dev_dbg(dev, "misc 5->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr2 + 20)); + + /* PTEST diff driver enable */ + ctrl_val = readl(brcmstb_priv->sde_ioaddr2); + ctrl_val |= BIT(21); + writel(ctrl_val, brcmstb_priv->sde_ioaddr2); + + dev_dbg(dev, "misc 0->%08x (%08x)\n", ctrl_val, readl(brcmstb_priv->sde_ioaddr2)); + + /* Wait for more than the minimum Tpvpgl time */ + msleep(100); + + if (brcmstb_priv->sde_pcie) { + struct of_changeset changeset; + static struct property okay_property = { + .name = "status", + .value = "okay", + .length = 5, + }; + + /* Enable the pcie controller */ + of_changeset_init(&changeset); + ret = of_changeset_update_property(&changeset, + brcmstb_priv->sde_pcie, + &okay_property); + if (ret) { + dev_err(dev, "%s: failed to update property - %d\n", __func__, + ret); + return -ENODEV; + } + ret = of_changeset_apply(&changeset); + } + + dev_dbg(dev, "%s -> %d\n", __func__, ret); + return ret; } static void sdhci_brcmstb_dumpregs(struct mmc_host *mmc) @@ -220,6 +401,7 @@ static void sdhci_brcmstb_dumpregs(struct mmc_host *mmc) static void sdhci_brcmstb_cqe_enable(struct mmc_host *mmc) { struct sdhci_host *host = mmc_priv(mmc); + struct cqhci_host *cq_host = mmc->cqe_private; u32 reg; reg = sdhci_readl(host, SDHCI_PRESENT_STATE); @@ -229,6 +411,22 @@ static void sdhci_brcmstb_cqe_enable(struct mmc_host *mmc) } sdhci_cqe_enable(mmc); + + /* + * The controller resets this register to a very short default interval + * whenever CQHCI is disabled. + * + * For removable cards CBC needs to be clear or card removal can hang + * the CQE. In polling mode, a CIT of 0x4000 "cycles" seems to produce the best + * throughput. + * + * For nonremovable cards, the specification default of CBC=1 CIT=0x1000 + * suffices. + */ + if (mmc->caps & MMC_CAP_NONREMOVABLE) + cqhci_writel(cq_host, 0x00011000, CQHCI_SSC1); + else + cqhci_writel(cq_host, 0x00004000, CQHCI_SSC1); } static const struct cqhci_host_ops sdhci_brcmstb_cqhci_ops = { @@ -245,11 +443,12 @@ static struct sdhci_ops sdhci_brcmstb_ops = { }; static struct sdhci_ops sdhci_brcmstb_ops_2712 = { - .set_clock = sdhci_set_clock, - .set_power = sdhci_set_power_and_bus_voltage, + .set_clock = sdhci_bcm2712_set_clock, + .set_power = sdhci_brcmstb_set_power, .set_bus_width = sdhci_set_bus_width, - .reset = sdhci_reset, + .reset = brcmstb_reset, .set_uhs_signaling = sdhci_set_uhs_signaling, + .init_sd_express = bcm2712_init_sd_express, }; static struct sdhci_ops sdhci_brcmstb_ops_7216 = { @@ -267,6 +466,8 @@ static struct sdhci_ops sdhci_brcmstb_ops_74165b0 = { }; static const struct brcmstb_match_priv match_priv_2712 = { + .flags = BRCMSTB_MATCH_FLAGS_USE_CARD_BUSY, + .hs400es = sdhci_brcmstb_hs400es, .cfginit = sdhci_brcmstb_cfginit_2712, .ops = &sdhci_brcmstb_ops_2712, }; @@ -370,8 +571,10 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev) struct sdhci_pltfm_host *pltfm_host; const struct of_device_id *match; struct sdhci_brcmstb_priv *priv; - u32 actual_clock_mhz; + u32 actual_clock_mhz, cqe; struct sdhci_host *host; + struct resource *iomem; + bool no_pinctrl = false; struct clk *clk; struct clk *base_clk = NULL; int res; @@ -394,12 +597,21 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev) return PTR_ERR(host); pltfm_host = sdhci_priv(host); + pltfm_host->clk = clk; + priv = sdhci_pltfm_priv(pltfm_host); - if (device_property_read_bool(&pdev->dev, "supports-cqe")) { + cqe = 0; + device_property_read_u32(&pdev->dev, "supports-cqe", &cqe); + if (cqe > 0) { priv->flags |= BRCMSTB_PRIV_FLAGS_HAS_CQE; match_priv->ops->irq = sdhci_brcmstb_cqhci_irq; } + priv->sde_pcie = of_parse_phandle(pdev->dev.of_node, + "sde-pcie", 0); + if (priv->sde_pcie) + priv->flags |= BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS; + /* Map in the non-standard CFG registers */ priv->cfg_regs = devm_platform_get_and_ioremap_resource(pdev, 1, NULL); if (IS_ERR(priv->cfg_regs)) { @@ -412,6 +624,43 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev) if (res) goto err; + priv->sde_1v8 = devm_regulator_get_optional(&pdev->dev, "sde-1v8"); + if (IS_ERR(priv->sde_1v8)) + priv->flags &= ~BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS; + + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 2); + if (iomem) { + priv->sde_ioaddr = devm_ioremap_resource(&pdev->dev, iomem); + if (IS_ERR(priv->sde_ioaddr)) + priv->sde_ioaddr = NULL; + } + + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 3); + if (iomem) { + priv->sde_ioaddr2 = devm_ioremap_resource(&pdev->dev, iomem); + if (IS_ERR(priv->sde_ioaddr2)) + priv->sde_ioaddr = NULL; + } + + priv->pinctrl = devm_pinctrl_get(&pdev->dev); + if (IS_ERR(priv->pinctrl)) { + no_pinctrl = true; + } + priv->pins_default = pinctrl_lookup_state(priv->pinctrl, "default"); + if (IS_ERR(priv->pins_default)) { + dev_dbg(&pdev->dev, "No pinctrl default state\n"); + no_pinctrl = true; + } + priv->pins_sdex = pinctrl_lookup_state(priv->pinctrl, "sd-express"); + if (IS_ERR(priv->pins_sdex)) { + dev_dbg(&pdev->dev, "No pinctrl sd-express state\n"); + no_pinctrl = true; + } + if (no_pinctrl || !priv->sde_ioaddr || !priv->sde_ioaddr2) { + priv->pinctrl = NULL; + priv->flags &= ~BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS; + } + /* * Automatic clock gating does not work for SD cards that may * voltage switch so only enable it for non-removable devices. @@ -428,6 +677,10 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev) (host->mmc->caps2 & MMC_CAP2_HS400_ES)) host->mmc_host_ops.hs400_enhanced_strobe = match_priv->hs400es; + if (host->ops->init_sd_express && + (priv->flags & BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS)) + host->mmc->caps2 |= MMC_CAP2_SD_EXP; + if (match_priv->cfginit) match_priv->cfginit(host); @@ -481,7 +734,6 @@ add_host: if (res) goto err; - pltfm_host->clk = clk; return res; err: diff --git a/drivers/mmc/host/sdhci-iproc.c b/drivers/mmc/host/sdhci-iproc.c index 35ef5c5f5146..a2c5e886bd35 100644 --- a/drivers/mmc/host/sdhci-iproc.c +++ b/drivers/mmc/host/sdhci-iproc.c @@ -198,6 +198,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_set_power_and_bus_voltage, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, .set_uhs_signaling = sdhci_set_uhs_signaling, diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index ee6b1096f709..4c1fccc03024 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -221,6 +221,7 @@ struct rk35xx_priv { struct dwcmshc_priv { struct clk *bus_clk; + struct clk *sdio_clk; int vendor_specific_area1; /* P_VENDOR_SPECIFIC_AREA1 reg */ int vendor_specific_area2; /* P_VENDOR_SPECIFIC_AREA2 reg */ @@ -289,6 +290,17 @@ static void dwcmshc_adma_write_desc(struct sdhci_host *host, void **desc, sdhci_adma_write_desc(host, desc, addr, len, cmd); } +static void dwcmshc_set_clock(struct sdhci_host *host, unsigned int clock) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); + + if (priv->sdio_clk) + clk_set_rate(priv->sdio_clk, clock); + + sdhci_set_clock(host, clock); +} + static unsigned int dwcmshc_get_max_clock(struct sdhci_host *host) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); @@ -1096,10 +1108,11 @@ static int sg2042_init(struct device *dev, struct sdhci_host *host, } static const struct sdhci_ops sdhci_dwcmshc_ops = { - .set_clock = sdhci_set_clock, + .set_clock = dwcmshc_set_clock, .set_bus_width = sdhci_set_bus_width, .set_uhs_signaling = dwcmshc_set_uhs_signaling, .get_max_clock = dwcmshc_get_max_clock, + .get_timeout_clock = sdhci_pltfm_clk_get_timeout_clock, .reset = sdhci_reset, .adma_write_desc = dwcmshc_adma_write_desc, .irq = dwcmshc_cqe_irq_handler, @@ -1172,8 +1185,10 @@ static const struct sdhci_ops sdhci_dwcmshc_sg2042_ops = { static const struct dwcmshc_pltfm_data sdhci_dwcmshc_pdata = { .pdata = { .ops = &sdhci_dwcmshc_ops, - .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, - .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, + .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | + SDHCI_QUIRK_BROKEN_CARD_DETECTION, + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | + SDHCI_QUIRK2_BROKEN_HS200, }, }; @@ -1188,13 +1203,26 @@ static const struct dwcmshc_pltfm_data sdhci_dwcmshc_bf3_pdata = { }; #endif +static const struct sdhci_pltfm_data sdhci_dwcmshc_rp1_pdata = { + .ops = &sdhci_dwcmshc_ops, + .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | + SDHCI_QUIRK_BROKEN_CARD_DETECTION, + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | + SDHCI_QUIRK2_BROKEN_HS200 | + SDHCI_QUIRK2_SPURIOUS_INT_RESP, +}; + static const struct dwcmshc_pltfm_data sdhci_dwcmshc_rk35xx_pdata = { .pdata = { .ops = &sdhci_dwcmshc_rk35xx_ops, .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL, .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | - SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN, + SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN | + SDHCI_QUIRK2_NO_SDR50 | + SDHCI_QUIRK2_NO_SDR104 | + SDHCI_QUIRK2_NO_SDR25, + }, .init = dwcmshc_rk35xx_init, .postinit = dwcmshc_rk35xx_postinit, @@ -1307,6 +1335,10 @@ dsbl_cqe_caps: static const struct of_device_id sdhci_dwcmshc_dt_ids[] = { { + .compatible = "raspberrypi,rp1-dwcmshc", + .data = &sdhci_dwcmshc_rp1_pdata, + }, + { .compatible = "rockchip,rk3588-dwcmshc", .data = &sdhci_dwcmshc_rk35xx_pdata, }, @@ -1398,13 +1430,32 @@ static int dwcmshc_probe(struct platform_device *pdev) priv->bus_clk = devm_clk_get(dev, "bus"); if (!IS_ERR(priv->bus_clk)) clk_prepare_enable(priv->bus_clk); + + pltfm_host->timeout_clk = devm_clk_get(dev, "timeout"); + if (!IS_ERR(pltfm_host->timeout_clk)) + err = clk_prepare_enable(pltfm_host->timeout_clk); + if (err) + goto free_pltfm; + + priv->sdio_clk = devm_clk_get_optional(&pdev->dev, "sdio"); + } + + pltfm_host->timeout_clk = devm_clk_get(&pdev->dev, "timeout"); + if (IS_ERR(pltfm_host->timeout_clk)) { + err = PTR_ERR(pltfm_host->timeout_clk); + dev_err(&pdev->dev, "failed to get timeout clk: %d\n", err); + goto free_pltfm; } + err = clk_prepare_enable(pltfm_host->timeout_clk); + if (err) + goto free_pltfm; err = mmc_of_parse(host->mmc); if (err) goto err_clk; sdhci_get_of_property(pdev); + sdhci_enable_v4_mode(host); priv->vendor_specific_area1 = sdhci_readl(host, DWCMSHC_P_VENDOR_AREA1) & DWCMSHC_AREA1_MASK; @@ -1464,6 +1515,7 @@ err_rpm: pm_runtime_put_noidle(dev); err_clk: clk_disable_unprepare(pltfm_host->clk); + clk_disable_unprepare(pltfm_host->timeout_clk); clk_disable_unprepare(priv->bus_clk); clk_bulk_disable_unprepare(priv->num_other_clks, priv->other_clks); return err; diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index 7f6ac636f040..ea58a8cdf33c 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c @@ -32,6 +32,14 @@ unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host) } EXPORT_SYMBOL_GPL(sdhci_pltfm_clk_get_max_clock); +unsigned int sdhci_pltfm_clk_get_timeout_clock(struct sdhci_host *host) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + + return clk_get_rate(pltfm_host->timeout_clk); +} +EXPORT_SYMBOL_GPL(sdhci_pltfm_clk_get_timeout_clock); + static const struct sdhci_ops sdhci_pltfm_ops = { .set_clock = sdhci_set_clock, .set_bus_width = sdhci_set_bus_width, diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h index 9c32e8a289d6..15d98c833c73 100644 --- a/drivers/mmc/host/sdhci-pltfm.h +++ b/drivers/mmc/host/sdhci-pltfm.h @@ -20,6 +20,7 @@ struct sdhci_pltfm_data { struct sdhci_pltfm_host { struct clk *clk; + struct clk *timeout_clk; /* migrate from sdhci_of_host */ unsigned int clock; @@ -105,6 +106,8 @@ extern void sdhci_pltfm_remove(struct platform_device *pdev); extern unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host); +extern unsigned int sdhci_pltfm_clk_get_timeout_clock(struct sdhci_host *host); + static inline void *sdhci_pltfm_priv(struct sdhci_pltfm_host *host) { return host->private; diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index ac7e11f37af7..65c1615f013c 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -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 @@ -1084,7 +1084,7 @@ void sdhci_initialize_data(struct sdhci_host *host, struct mmc_data *data) WARN_ON(host->data); /* Sanity checks */ - BUG_ON(data->blksz * data->blocks > 524288); + BUG_ON(data->blksz * data->blocks > host->mmc->max_req_size); BUG_ON(data->blksz > host->mmc->max_blk_size); BUG_ON(data->blocks > 65535); @@ -1736,6 +1736,12 @@ static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) if (host->use_external_dma) sdhci_external_dma_pre_transfer(host, cmd); + if (host->quirks2 & SDHCI_QUIRK2_SPURIOUS_INT_RESP) { + host->ier |= SDHCI_INT_RESPONSE; + sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); + sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); + } + sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); return true; @@ -3076,6 +3082,15 @@ static void sdhci_card_event(struct mmc_host *mmc) spin_unlock_irqrestore(&host->lock, flags); } +static int sdhci_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios) +{ + struct sdhci_host *host = mmc_priv(mmc); + + if (!host->ops->init_sd_express) + return -EOPNOTSUPP; + return host->ops->init_sd_express(host, ios); +} + static const struct mmc_host_ops sdhci_ops = { .request = sdhci_request, .post_req = sdhci_post_req, @@ -3091,6 +3106,7 @@ static const struct mmc_host_ops sdhci_ops = { .execute_tuning = sdhci_execute_tuning, .card_event = sdhci_card_event, .card_busy = sdhci_card_busy, + .init_sd_express = sdhci_init_sd_express, }; /*****************************************************************************\ @@ -3245,7 +3261,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_err_stats_inc(host, REQ_TIMEOUT); sdhci_dumpregs(host); @@ -3268,7 +3284,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_err_stats_inc(host, REQ_TIMEOUT); sdhci_dumpregs(host); @@ -3332,6 +3348,11 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *intmask_p) if (intmask & SDHCI_INT_TIMEOUT) { host->cmd->error = -ETIMEDOUT; sdhci_err_stats_inc(host, CMD_TIMEOUT); + if (host->quirks2 & SDHCI_QUIRK2_SPURIOUS_INT_RESP) { + host->ier &= ~SDHCI_INT_RESPONSE; + sdhci_writel(host, host->ier, SDHCI_INT_ENABLE); + sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE); + } } else { host->cmd->error = -EILSEQ; if (!mmc_op_tuning(host->cmd->opcode)) @@ -4618,6 +4639,15 @@ int sdhci_setup_host(struct sdhci_host *host) !(host->quirks2 & SDHCI_QUIRK2_BROKEN_DDR50)) mmc->caps |= MMC_CAP_UHS_DDR50; + if (host->quirks2 & SDHCI_QUIRK2_NO_SDR25) + mmc->caps &= ~MMC_CAP_UHS_SDR25; + + if (host->quirks2 & SDHCI_QUIRK2_NO_SDR50) + mmc->caps &= ~MMC_CAP_UHS_SDR50; + + if (host->quirks2 & SDHCI_QUIRK2_NO_SDR104) + mmc->caps &= ~MMC_CAP_UHS_SDR104; + /* Does the host need tuning for SDR50? */ if (host->caps1 & SDHCI_USE_SDR50_TUNING) host->flags |= SDHCI_SDR50_NEEDS_TUNING; @@ -4732,11 +4762,16 @@ int sdhci_setup_host(struct sdhci_host *host) spin_lock_init(&host->lock); /* - * Maximum number of sectors in one transfer. Limited by SDMA boundary - * size (512KiB). Note some tuning modes impose a 4MiB limit, but this - * is less anyway. + * Maximum number of sectors in one transfer. + * 4MiB is preferred for multi-descriptor DMA as a) card sequential + * write speeds are only guaranteed with a 4MiB write length and + * b) most tuning modes require a 4MiB limit. + * SDMA has a 512KiB boundary size. */ - mmc->max_req_size = 524288; + if (host->flags & SDHCI_USE_ADMA) + mmc->max_req_size = SZ_4M; + else + mmc->max_req_size = SZ_512K; /* * Maximum number of segments. Depends on if the hardware diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 58fcbeaf281e..9d42eb94a1dc 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -537,6 +537,14 @@ struct sdhci_host { /* Issue CMD and DATA reset together */ #define SDHCI_QUIRK2_ISSUE_CMD_DAT_RESET_TOGETHER (1<<19) +/* Quirks to ignore a speed if a that speed is unreliable */ +#define SDHCI_QUIRK2_NO_SDR25 (1<<19) +#define SDHCI_QUIRK2_NO_SDR50 (1<<20) +#define SDHCI_QUIRK2_NO_SDR104 (1<<21) + +/* Command timeouts may generate a trailing INT_RESPONSE later */ +#define SDHCI_QUIRK2_SPURIOUS_INT_RESP (1<<31) + int irq; /* Device IRQ */ void __iomem *ioaddr; /* Mapped address */ phys_addr_t mapbase; /* physical address base */ @@ -724,6 +732,7 @@ struct sdhci_ops { void (*dump_vendor_regs)(struct sdhci_host *host); void (*dump_uhs2_regs)(struct sdhci_host *host); void (*uhs2_pre_detect_init)(struct sdhci_host *host); + int (*init_sd_express)(struct sdhci_host *host, struct mmc_ios *ios); }; #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS |
