Commit 20077583 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mmc-v6.8' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc

Pull MMC updates from Ulf Hansson:
 "MMC core:
   - Don't force a retune before eMMC RPMB switch
   - Add optional HS400 tuning in HS400es initialization
   - Add a sysfs node to for write-protect-group-size
   - Add re-tuning test to the mmc-test module
   - Use mrq.sbc to support close-ended ioctl requests

  MMC host:
   - mmci: Add support for SDIO in-band irqs for the stm32 variant
   - mmc_spi: Remove broken support custom DMA mapped buffers
   - mtk-sd: Improve and extend the support for tunings
   - renesas_sdhi: Document support for the RZ/Five variant
   - sdhci_am654: Drop support for the ti,otap-del-sel DT property
   - sdhci-brcmstb: Add support for the brcm 74165b0 variant
   - sdhci-msm: Add compatibles for IPQ4019 and IPQ8074
   - sdhci-of-dwcmshc: Add support for the T-Head TH1520 variant
   - sdhci-xenon: Add support for the Marvell ac5 variant"

* tag 'mmc-v6.8' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: (27 commits)
  mmc: xenon: Add ac5 support via bounce buffer
  dt-bindings: mmc: add Marvell ac5
  mmc: sdhci-brcmstb: add new sdhci reset sequence for brcm 74165b0
  dt-bindings: mmc: brcm,sdhci-brcmstb: Add support for 74165b0
  mmc: core: Do not force a retune before RPMB switch
  mmc: core: Add HS400 tuning in HS400es initialization
  mmc: sdhci_omap: Fix TI SoC dependencies
  mmc: sdhci_am654: Fix TI SoC dependencies
  mmc: core: Add wp_grp_size sysfs node
  mmc: mmc_test: Add re-tuning test
  mmc: mmc_spi: remove custom DMA mapped buffers
  dt-bindings: mmc: sdhci-msm: document dedicated IPQ4019 and IPQ8074
  dt-bindings: mmc: synopsys-dw-mshc: add iommus for Intel SocFPGA
  mmc: mtk-sd: Extend number of tuning steps
  dt-bindings: mmc: mtk-sd: add tuning steps related property
  mmc: sdhci-omap: don't misuse kernel-doc marker
  mmc: mtk-sd: Increase the verbosity of msdc_track_cmd_data
  mmc: core: Use mrq.sbc in close-ended ffu
  mmc: sdhci_am654: Drop lookup for deprecated ti,otap-del-sel
  mmc: sdhci-of-dwcmshc: Use logical OR instead of bitwise OR in dwcmshc_probe()
  ...
parents 0c4b09cb 5d402133
......@@ -226,8 +226,8 @@ examples:
interrupt-parent = <&gic>;
interrupts = <0 48 4>;
reg = <0xff160000 0x1000>;
clocks = <&clk200>, <&clk200>;
clock-names = "clk_xin", "clk_ahb";
clocks = <&clk200>, <&clk200>, <&clk1200>;
clock-names = "clk_xin", "clk_ahb", "gate";
clock-output-names = "clk_out_sd0", "clk_in_sd0";
#clock-cells = <1>;
clk-phase-sd-hs = <63>, <72>;
......@@ -239,8 +239,8 @@ examples:
interrupt-parent = <&gic>;
interrupts = <0 126 4>;
reg = <0xf1040000 0x10000>;
clocks = <&clk200>, <&clk200>;
clock-names = "clk_xin", "clk_ahb";
clocks = <&clk200>, <&clk200>, <&clk1200>;
clock-names = "clk_xin", "clk_ahb", "gate";
clock-output-names = "clk_out_sd0", "clk_in_sd0";
#clock-cells = <1>;
clk-phase-sd-hs = <132>, <60>;
......
......@@ -20,10 +20,8 @@ properties:
- const: brcm,sdhci-brcmstb
- items:
- enum:
- brcm,bcm74165b0-sdhci
- brcm,bcm7445-sdhci
- const: brcm,sdhci-brcmstb
- items:
- enum:
- brcm,bcm7425-sdhci
- const: brcm,sdhci-brcmstb
......
......@@ -27,7 +27,9 @@ properties:
- marvell,armada-ap806-sdhci
- items:
- const: marvell,armada-ap807-sdhci
- enum:
- marvell,armada-ap807-sdhci
- marvell,ac5-sdhci
- const: marvell,armada-ap806-sdhci
- items:
......
......@@ -145,6 +145,15 @@ properties:
minimum: 0
maximum: 7
mediatek,tuning-step:
$ref: /schemas/types.yaml#/definitions/uint32
description:
Some SoCs need extend tuning step for better delay value to avoid CRC issue.
If not present, default tuning step is 32. For eMMC and SD, this can yield
satisfactory calibration results in most cases.
enum: [32, 64]
default: 32
resets:
maxItems: 1
......
......@@ -56,7 +56,7 @@ properties:
- renesas,sdhi-r8a77980 # R-Car V3H
- renesas,sdhi-r8a77990 # R-Car E3
- renesas,sdhi-r8a77995 # R-Car D3
- renesas,sdhi-r9a07g043 # RZ/G2UL
- renesas,sdhi-r9a07g043 # RZ/G2UL and RZ/Five
- renesas,sdhi-r9a07g044 # RZ/G2{L,LC}
- renesas,sdhi-r9a07g054 # RZ/V2L
- renesas,sdhi-r9a08g045 # RZ/G3S
......
......@@ -22,6 +22,8 @@ properties:
- items:
- enum:
- qcom,apq8084-sdhci
- qcom,ipq4019-sdhci
- qcom,ipq8074-sdhci
- qcom,msm8226-sdhci
- qcom,msm8953-sdhci
- qcom,msm8974-sdhci
......
......@@ -19,6 +19,7 @@ properties:
- rockchip,rk3568-dwcmshc
- rockchip,rk3588-dwcmshc
- snps,dwcmshc-sdhci
- thead,th1520-dwcmshc
reg:
maxItems: 1
......
......@@ -35,6 +35,9 @@ properties:
- const: biu
- const: ciu
iommus:
maxItems: 1
altr,sysmgr-syscon:
$ref: /schemas/types.yaml#/definitions/phandle-array
items:
......@@ -62,6 +65,7 @@ allOf:
altr,sysmgr-syscon: true
else:
properties:
iommus: false
altr,sysmgr-syscon: false
required:
......
......@@ -400,6 +400,10 @@ struct mmc_blk_ioc_data {
struct mmc_ioc_cmd ic;
unsigned char *buf;
u64 buf_bytes;
unsigned int flags;
#define MMC_BLK_IOC_DROP BIT(0) /* drop this mrq */
#define MMC_BLK_IOC_SBC BIT(1) /* use mrq.sbc */
struct mmc_rpmb_data *rpmb;
};
......@@ -465,7 +469,7 @@ static int mmc_blk_ioctl_copy_to_user(struct mmc_ioc_cmd __user *ic_ptr,
}
static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
struct mmc_blk_ioc_data *idata)
struct mmc_blk_ioc_data **idatas, int i)
{
struct mmc_command cmd = {}, sbc = {};
struct mmc_data data = {};
......@@ -475,10 +479,18 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
unsigned int busy_timeout_ms;
int err;
unsigned int target_part;
struct mmc_blk_ioc_data *idata = idatas[i];
struct mmc_blk_ioc_data *prev_idata = NULL;
if (!card || !md || !idata)
return -EINVAL;
if (idata->flags & MMC_BLK_IOC_DROP)
return 0;
if (idata->flags & MMC_BLK_IOC_SBC)
prev_idata = idatas[i - 1];
/*
* The RPMB accesses comes in from the character device, so we
* need to target these explicitly. Else we just target the
......@@ -532,7 +544,7 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
return err;
}
if (idata->rpmb) {
if (idata->rpmb || prev_idata) {
sbc.opcode = MMC_SET_BLOCK_COUNT;
/*
* We don't do any blockcount validation because the max size
......@@ -540,6 +552,8 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
* 'Reliable Write' bit here.
*/
sbc.arg = data.blocks | (idata->ic.write_flag & BIT(31));
if (prev_idata)
sbc.arg = prev_idata->ic.arg;
sbc.flags = MMC_RSP_R1 | MMC_CMD_AC;
mrq.sbc = &sbc;
}
......@@ -557,6 +571,15 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
mmc_wait_for_req(card->host, &mrq);
memcpy(&idata->ic.response, cmd.resp, sizeof(cmd.resp));
if (prev_idata) {
memcpy(&prev_idata->ic.response, sbc.resp, sizeof(sbc.resp));
if (sbc.error) {
dev_err(mmc_dev(card->host), "%s: sbc error %d\n",
__func__, sbc.error);
return sbc.error;
}
}
if (cmd.error) {
dev_err(mmc_dev(card->host), "%s: cmd error %d\n",
__func__, cmd.error);
......@@ -1034,6 +1057,20 @@ static inline void mmc_blk_reset_success(struct mmc_blk_data *md, int type)
md->reset_done &= ~type;
}
static void mmc_blk_check_sbc(struct mmc_queue_req *mq_rq)
{
struct mmc_blk_ioc_data **idata = mq_rq->drv_op_data;
int i;
for (i = 1; i < mq_rq->ioc_count; i++) {
if (idata[i - 1]->ic.opcode == MMC_SET_BLOCK_COUNT &&
mmc_op_multi(idata[i]->ic.opcode)) {
idata[i - 1]->flags |= MMC_BLK_IOC_DROP;
idata[i]->flags |= MMC_BLK_IOC_SBC;
}
}
}
/*
* The non-block commands come back from the block layer after it queued it and
* processed it with all other requests and then they get issued in this
......@@ -1061,11 +1098,14 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req)
if (ret)
break;
}
mmc_blk_check_sbc(mq_rq);
fallthrough;
case MMC_DRV_OP_IOCTL_RPMB:
idata = mq_rq->drv_op_data;
for (i = 0, ret = 0; i < mq_rq->ioc_count; i++) {
ret = __mmc_blk_ioctl_cmd(card, md, idata[i]);
ret = __mmc_blk_ioctl_cmd(card, md, idata, i);
if (ret)
break;
}
......
......@@ -119,13 +119,12 @@ void mmc_retune_enable(struct mmc_host *host)
/*
* Pause re-tuning for a small set of operations. The pause begins after the
* next command and after first doing re-tuning.
* next command.
*/
void mmc_retune_pause(struct mmc_host *host)
{
if (!host->retune_paused) {
host->retune_paused = 1;
mmc_retune_needed(host);
mmc_retune_hold(host);
}
}
......
......@@ -136,6 +136,17 @@ static void mmc_set_erase_size(struct mmc_card *card)
mmc_init_erase(card);
}
static void mmc_set_wp_grp_size(struct mmc_card *card)
{
if (card->ext_csd.erase_group_def & 1)
card->wp_grp_size = card->ext_csd.hc_erase_size *
card->ext_csd.raw_hc_erase_gap_size;
else
card->wp_grp_size = card->csd.erase_size *
(card->csd.wp_grp_size + 1);
}
/*
* Given a 128-bit response, decode to our card CSD structure.
*/
......@@ -186,6 +197,7 @@ static int mmc_decode_csd(struct mmc_card *card)
b = UNSTUFF_BITS(resp, 37, 5);
csd->erase_size = (a + 1) * (b + 1);
csd->erase_size <<= csd->write_blkbits - 9;
csd->wp_grp_size = UNSTUFF_BITS(resp, 32, 5);
}
return 0;
......@@ -613,11 +625,6 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
} else {
card->ext_csd.data_tag_unit_size = 0;
}
card->ext_csd.max_packed_writes =
ext_csd[EXT_CSD_MAX_PACKED_WRITES];
card->ext_csd.max_packed_reads =
ext_csd[EXT_CSD_MAX_PACKED_READS];
} else {
card->ext_csd.data_sector_size = 512;
}
......@@ -790,6 +797,7 @@ MMC_DEV_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
MMC_DEV_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year);
MMC_DEV_ATTR(erase_size, "%u\n", card->erase_size << 9);
MMC_DEV_ATTR(preferred_erase_size, "%u\n", card->pref_erase << 9);
MMC_DEV_ATTR(wp_grp_size, "%u\n", card->wp_grp_size << 9);
MMC_DEV_ATTR(ffu_capable, "%d\n", card->ext_csd.ffu_capable);
MMC_DEV_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
MMC_DEV_ATTR(manfid, "0x%06x\n", card->cid.manfid);
......@@ -850,6 +858,7 @@ static struct attribute *mmc_std_attrs[] = {
&dev_attr_date.attr,
&dev_attr_erase_size.attr,
&dev_attr_preferred_erase_size.attr,
&dev_attr_wp_grp_size.attr,
&dev_attr_fwrev.attr,
&dev_attr_ffu_capable.attr,
&dev_attr_hwrev.attr,
......@@ -1764,7 +1773,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
mmc_set_erase_size(card);
}
}
mmc_set_wp_grp_size(card);
/*
* Ensure eMMC user default partition is enabled
*/
......@@ -1822,8 +1831,13 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
if (err)
goto free_card;
} else if (!mmc_card_hs400es(card)) {
} else if (mmc_card_hs400es(card)) {
if (host->ops->execute_hs400_tuning) {
err = host->ops->execute_hs400_tuning(host, card);
if (err)
goto free_card;
}
} else {
/* Select the desired bus width optionally */
err = mmc_select_bus_width(card);
if (err > 0 && mmc_card_hs(card)) {
......
......@@ -1904,7 +1904,7 @@ static unsigned int mmc_test_rnd_num(unsigned int rnd_cnt)
}
static int mmc_test_rnd_perf(struct mmc_test_card *test, int write, int print,
unsigned long sz)
unsigned long sz, int secs, int force_retuning)
{
unsigned int dev_addr, cnt, rnd_addr, range1, range2, last_ea = 0, ea;
unsigned int ssz;
......@@ -1921,7 +1921,7 @@ static int mmc_test_rnd_perf(struct mmc_test_card *test, int write, int print,
for (cnt = 0; cnt < UINT_MAX; cnt++) {
ktime_get_ts64(&ts2);
ts = timespec64_sub(ts2, ts1);
if (ts.tv_sec >= 10)
if (ts.tv_sec >= secs)
break;
ea = mmc_test_rnd_num(range1);
if (ea == last_ea)
......@@ -1929,6 +1929,8 @@ static int mmc_test_rnd_perf(struct mmc_test_card *test, int write, int print,
last_ea = ea;
dev_addr = rnd_addr + test->card->pref_erase * ea +
ssz * mmc_test_rnd_num(range2);
if (force_retuning)
mmc_retune_needed(test->card->host);
ret = mmc_test_area_io(test, sz, dev_addr, write, 0, 0);
if (ret)
return ret;
......@@ -1953,24 +1955,35 @@ static int mmc_test_random_perf(struct mmc_test_card *test, int write)
*/
if (write) {
next = rnd_next;
ret = mmc_test_rnd_perf(test, write, 0, sz);
ret = mmc_test_rnd_perf(test, write, 0, sz, 10, 0);
if (ret)
return ret;
rnd_next = next;
}
ret = mmc_test_rnd_perf(test, write, 1, sz);
ret = mmc_test_rnd_perf(test, write, 1, sz, 10, 0);
if (ret)
return ret;
}
sz = t->max_tfr;
if (write) {
next = rnd_next;
ret = mmc_test_rnd_perf(test, write, 0, sz);
ret = mmc_test_rnd_perf(test, write, 0, sz, 10, 0);
if (ret)
return ret;
rnd_next = next;
}
return mmc_test_rnd_perf(test, write, 1, sz);
return mmc_test_rnd_perf(test, write, 1, sz, 10, 0);
}
static int mmc_test_retuning(struct mmc_test_card *test)
{
if (!mmc_can_retune(test->card->host)) {
pr_info("%s: No retuning - test skipped\n",
mmc_hostname(test->card->host));
return RESULT_UNSUP_HOST;
}
return mmc_test_rnd_perf(test, 0, 0, 8192, 30, 1);
}
/*
......@@ -2921,6 +2934,14 @@ static const struct mmc_test_case mmc_test_cases[] = {
.run = mmc_test_cmds_during_write_cmd23_nonblock,
.cleanup = mmc_test_area_cleanup,
},
{
.name = "Re-tuning reliability",
.prepare = mmc_test_area_prepare,
.run = mmc_test_retuning,
.cleanup = mmc_test_area_cleanup,
},
};
static DEFINE_MUTEX(mmc_test_lock);
......
......@@ -1026,14 +1026,15 @@ config MMC_SDHCI_XENON
config MMC_SDHCI_OMAP
tristate "TI SDHCI Controller Support"
depends on ARCH_OMAP2PLUS || ARCH_KEYSTONE || COMPILE_TEST
depends on MMC_SDHCI_PLTFM && OF
select THERMAL
imply TI_SOC_THERMAL
select MMC_SDHCI_EXTERNAL_DMA if DMA_ENGINE
help
This selects the Secure Digital Host Controller Interface (SDHCI)
support present in TI's DRA7 SOCs. The controller supports
SD/MMC/SDIO devices.
support present in TI's Keystone/OMAP2+/DRA7 SOCs. The controller
supports SD/MMC/SDIO devices.
If you have a controller with this interface, say Y or M here.
......@@ -1041,14 +1042,15 @@ config MMC_SDHCI_OMAP
config MMC_SDHCI_AM654
tristate "Support for the SDHCI Controller in TI's AM654 SOCs"
depends on ARCH_K3 || COMPILE_TEST
depends on MMC_SDHCI_PLTFM && OF
select MMC_SDHCI_IO_ACCESSORS
select MMC_CQHCI
select REGMAP_MMIO
help
This selects the Secure Digital Host Controller Interface (SDHCI)
support present in TI's AM654 SOCs. The controller supports
SD/MMC/SDIO devices.
support present in TI's AM65x/AM64x/AM62x/J721E SOCs. The controller
supports SD/MMC/SDIO devices.
If you have a controller with this interface, say Y or M here.
......
This diff is collapsed.
......@@ -273,6 +273,7 @@ static struct variant_data variant_stm32_sdmmc = {
.datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
.stm32_idmabsize_mask = GENMASK(12, 5),
.stm32_idmabsize_align = BIT(5),
.supports_sdio_irq = true,
.busy_timeout = true,
.busy_detect = true,
.busy_detect_flag = MCI_STM32_BUSYD0,
......@@ -300,6 +301,7 @@ static struct variant_data variant_stm32_sdmmcv2 = {
.datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
.stm32_idmabsize_mask = GENMASK(16, 5),
.stm32_idmabsize_align = BIT(5),
.supports_sdio_irq = true,
.dma_lli = true,
.busy_timeout = true,
.busy_detect = true,
......@@ -328,6 +330,7 @@ static struct variant_data variant_stm32_sdmmcv3 = {
.datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN,
.stm32_idmabsize_mask = GENMASK(16, 6),
.stm32_idmabsize_align = BIT(6),
.supports_sdio_irq = true,
.dma_lli = true,
.busy_timeout = true,
.busy_detect = true,
......@@ -421,8 +424,9 @@ void mmci_write_pwrreg(struct mmci_host *host, u32 pwr)
*/
static void mmci_write_datactrlreg(struct mmci_host *host, u32 datactrl)
{
/* Keep busy mode in DPSM if enabled */
datactrl |= host->datactrl_reg & host->variant->busy_dpsm_flag;
/* Keep busy mode in DPSM and SDIO mask if enabled */
datactrl |= host->datactrl_reg & (host->variant->busy_dpsm_flag |
host->variant->datactrl_mask_sdio);
if (host->datactrl_reg != datactrl) {
host->datactrl_reg = datactrl;
......@@ -1762,6 +1766,25 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
static void mmci_write_sdio_irq_bit(struct mmci_host *host, int enable)
{
void __iomem *base = host->base;
u32 mask = readl_relaxed(base + MMCIMASK0);
if (enable)
writel_relaxed(mask | MCI_ST_SDIOITMASK, base + MMCIMASK0);
else
writel_relaxed(mask & ~MCI_ST_SDIOITMASK, base + MMCIMASK0);
}
static void mmci_signal_sdio_irq(struct mmci_host *host, u32 status)
{
if (status & MCI_ST_SDIOIT) {
mmci_write_sdio_irq_bit(host, 0);
sdio_signal_irq(host->mmc);
}
}
/*
* Handle completion of command and data transfers.
*/
......@@ -1806,6 +1829,9 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
mmci_data_irq(host, host->data, status);
}
if (host->variant->supports_sdio_irq)
mmci_signal_sdio_irq(host, status);
/*
* Busy detection has been handled by mmci_cmd_irq() above.
* Clear the status bit to prevent polling in IRQ context.
......@@ -2042,6 +2068,35 @@ static int mmci_sig_volt_switch(struct mmc_host *mmc, struct mmc_ios *ios)
return ret;
}
static void mmci_enable_sdio_irq(struct mmc_host *mmc, int enable)
{
struct mmci_host *host = mmc_priv(mmc);
unsigned long flags;
if (enable)
/* Keep the SDIO mode bit if SDIO irqs are enabled */
pm_runtime_get_sync(mmc_dev(mmc));
spin_lock_irqsave(&host->lock, flags);
mmci_write_sdio_irq_bit(host, enable);
spin_unlock_irqrestore(&host->lock, flags);
if (!enable) {
pm_runtime_mark_last_busy(mmc_dev(mmc));
pm_runtime_put_autosuspend(mmc_dev(mmc));
}
}
static void mmci_ack_sdio_irq(struct mmc_host *mmc)
{
struct mmci_host *host = mmc_priv(mmc);
unsigned long flags;
spin_lock_irqsave(&host->lock, flags);
mmci_write_sdio_irq_bit(host, 1);
spin_unlock_irqrestore(&host->lock, flags);
}
static struct mmc_host_ops mmci_ops = {
.request = mmci_request,
.pre_req = mmci_pre_request,
......@@ -2317,6 +2372,16 @@ static int mmci_probe(struct amba_device *dev,
mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
}
if (variant->supports_sdio_irq && host->mmc->caps & MMC_CAP_SDIO_IRQ) {
mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
mmci_ops.enable_sdio_irq = mmci_enable_sdio_irq;
mmci_ops.ack_sdio_irq = mmci_ack_sdio_irq;
mmci_write_datactrlreg(host,
host->variant->datactrl_mask_sdio);
}
/* Variants with mandatory busy timeout in HW needs R1B responses. */
if (variant->busy_timeout)
mmc->caps |= MMC_CAP_NEED_RSP_BUSY;
......
......@@ -331,6 +331,7 @@ enum mmci_busy_state {
* register.
* @opendrain: bitmask identifying the OPENDRAIN bit inside MMCIPOWER register
* @dma_lli: true if variant has dma link list feature.
* @supports_sdio_irq: allow SD I/O card to interrupt the host
* @stm32_idmabsize_mask: stm32 sdmmc idma buffer size.
* @dma_flow_controller: use peripheral as flow controller for DMA.
*/
......@@ -377,6 +378,7 @@ struct variant_data {
u32 start_err;
u32 opendrain;
u8 dma_lli:1;
bool supports_sdio_irq;
u32 stm32_idmabsize_mask;
u32 stm32_idmabsize_align;
bool dma_flow_controller;
......
This diff is collapsed.
......@@ -6,6 +6,7 @@
*/
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/mmc/host.h>
#include <linux/module.h>
#include <linux/of.h>
......@@ -44,8 +45,13 @@ struct brcmstb_match_priv {
static inline void enable_clock_gating(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_brcmstb_priv *priv = sdhci_pltfm_priv(pltfm_host);
u32 reg;
if (!(priv->flags & BRCMSTB_PRIV_FLAGS_GATE_CLOCK))
return;
reg = sdhci_readl(host, SDHCI_VENDOR);
reg |= SDHCI_VENDOR_GATE_SDCLK_EN;
sdhci_writel(host, reg, SDHCI_VENDOR);
......@@ -53,13 +59,52 @@ static inline void enable_clock_gating(struct sdhci_host *host)
static void brcmstb_reset(struct sdhci_host *host, u8 mask)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_brcmstb_priv *priv = sdhci_pltfm_priv(pltfm_host);
sdhci_and_cqhci_reset(host, mask);
/* Reset will clear this, so re-enable it */
if (priv->flags & BRCMSTB_PRIV_FLAGS_GATE_CLOCK)
enable_clock_gating(host);
}
static void brcmstb_sdhci_reset_cmd_data(struct sdhci_host *host, u8 mask)
{
u32 new_mask = (mask & (SDHCI_RESET_CMD | SDHCI_RESET_DATA)) << 24;
int ret;
u32 reg;
/*
* SDHCI_CLOCK_CONTROL register CARD_EN and CLOCK_INT_EN bits shall
* be set along with SOFTWARE_RESET register RESET_CMD or RESET_DATA
* bits, hence access SDHCI_CLOCK_CONTROL register as 32-bit register
*/
new_mask |= SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_INT_EN;
reg = sdhci_readl(host, SDHCI_CLOCK_CONTROL);
sdhci_writel(host, reg | new_mask, SDHCI_CLOCK_CONTROL);
reg = sdhci_readb(host, SDHCI_SOFTWARE_RESET);
ret = read_poll_timeout_atomic(sdhci_readb, reg, !(reg & mask),
10, 10000, false,
host, SDHCI_SOFTWARE_RESET);
if (ret) {
pr_err("%s: Reset 0x%x never completed.\n",
mmc_hostname(host->mmc), (int)mask);
sdhci_err_stats_inc(host, CTRL_TIMEOUT);
sdhci_dumpregs(host);
}
}
static void brcmstb_reset_74165b0(struct sdhci_host *host, u8 mask)
{
/* take care of RESET_ALL as usual */
if (mask & SDHCI_RESET_ALL)
sdhci_and_cqhci_reset(host, SDHCI_RESET_ALL);
/* cmd and/or data treated differently on this core */
if (mask & (SDHCI_RESET_CMD | SDHCI_RESET_DATA))
brcmstb_sdhci_reset_cmd_data(host, mask);
/* Reset will clear this, so re-enable it */
enable_clock_gating(host);
}
......@@ -162,6 +207,13 @@ static struct sdhci_ops sdhci_brcmstb_ops_7216 = {
.set_uhs_signaling = sdhci_brcmstb_set_uhs_signaling,
};
static struct sdhci_ops sdhci_brcmstb_ops_74165b0 = {
.set_clock = sdhci_brcmstb_set_clock,
.set_bus_width = sdhci_set_bus_width,
.reset = brcmstb_reset_74165b0,
.set_uhs_signaling = sdhci_brcmstb_set_uhs_signaling,
};
static struct brcmstb_match_priv match_priv_7425 = {
.flags = BRCMSTB_MATCH_FLAGS_NO_64BIT |
BRCMSTB_MATCH_FLAGS_BROKEN_TIMEOUT,
......@@ -179,10 +231,17 @@ static const struct brcmstb_match_priv match_priv_7216 = {
.ops = &sdhci_brcmstb_ops_7216,
};
static struct brcmstb_match_priv match_priv_74165b0 = {
.flags = BRCMSTB_MATCH_FLAGS_HAS_CLOCK_GATE,
.hs400es = sdhci_brcmstb_hs400es,
.ops = &sdhci_brcmstb_ops_74165b0,
};
static const struct of_device_id __maybe_unused sdhci_brcm_of_match[] = {
{ .compatible = "brcm,bcm7425-sdhci", .data = &match_priv_7425 },
{ .compatible = "brcm,bcm7445-sdhci", .data = &match_priv_7445 },
{ .compatible = "brcm,bcm7216-sdhci", .data = &match_priv_7216 },
{ .compatible = "brcm,bcm74165b0-sdhci", .data = &match_priv_74165b0 },
{},
};
......
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0-only
/**
/*
* SDHCI Controller driver for TI's OMAP SoCs
*
* Copyright (C) 2017 Texas Instruments
......
......@@ -18,6 +18,8 @@
#include <linux/of.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/mm.h>
#include <linux/dma-mapping.h>
#include "sdhci-pltfm.h"
#include "sdhci-xenon.h"
......@@ -422,6 +424,7 @@ static int xenon_probe_params(struct platform_device *pdev)
struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
u32 sdhc_id, nr_sdhc;
u32 tuning_count;
struct sysinfo si;
/* Disable HS200 on Armada AP806 */
if (priv->hw_version == XENON_AP806)
......@@ -450,6 +453,23 @@ static int xenon_probe_params(struct platform_device *pdev)
}
priv->tuning_count = tuning_count;
/*
* AC5/X/IM HW has only 31-bits passed in the crossbar switch.
* If we have more than 2GB of memory, this means we might pass
* memory pointers which are above 2GB and which cannot be properly
* represented. In this case, disable ADMA, 64-bit DMA and allow only SDMA.
* This effectively will enable bounce buffer quirk in the
* generic SDHCI driver, which will make sure DMA is only done
* from supported memory regions:
*/
if (priv->hw_version == XENON_AC5) {
si_meminfo(&si);
if (si.totalram * si.mem_unit > SZ_2G) {
host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
host->quirks2 |= SDHCI_QUIRK2_BROKEN_64_BIT_DMA;
}
}
return xenon_phy_parse_params(dev, host);
}
......@@ -562,6 +582,16 @@ static int xenon_probe(struct platform_device *pdev)
goto remove_sdhc;
pm_runtime_put_autosuspend(&pdev->dev);
/*
* If we previously detected AC5 with over 2GB of memory,
* then we disable ADMA and 64-bit DMA.
* This means generic SDHCI driver has set the DMA mask to
* 32-bit. Since DDR starts at 0x2_0000_0000, we must use
* 34-bit DMA mask to access this DDR memory:
*/
if (priv->hw_version == XENON_AC5 &&
host->quirks2 & SDHCI_QUIRK2_BROKEN_64_BIT_DMA)
dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(34));
return 0;
......@@ -680,6 +710,7 @@ static const struct of_device_id sdhci_xenon_dt_ids[] = {
{ .compatible = "marvell,armada-ap807-sdhci", .data = (void *)XENON_AP807},
{ .compatible = "marvell,armada-cp110-sdhci", .data = (void *)XENON_CP110},
{ .compatible = "marvell,armada-3700-sdhci", .data = (void *)XENON_A3700},
{ .compatible = "marvell,ac5-sdhci", .data = (void *)XENON_AC5},
{}
};
MODULE_DEVICE_TABLE(of, sdhci_xenon_dt_ids);
......
......@@ -57,7 +57,8 @@ enum xenon_variant {
XENON_A3700,
XENON_AP806,
XENON_AP807,
XENON_CP110
XENON_CP110,
XENON_AC5
};
struct xenon_priv {
......
......@@ -2841,7 +2841,7 @@ void sdhci_send_tuning(struct sdhci_host *host, u32 opcode)
}
EXPORT_SYMBOL_GPL(sdhci_send_tuning);
static int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
{
int i;
......@@ -2879,6 +2879,7 @@ static int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
sdhci_reset_tuning(host);
return -EAGAIN;
}
EXPORT_SYMBOL_GPL(__sdhci_execute_tuning);
int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
{
......
......@@ -793,6 +793,7 @@ void sdhci_set_bus_width(struct sdhci_host *host, int width);
void sdhci_reset(struct sdhci_host *host, u8 mask);
void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing);
int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode);
void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios);
int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
struct mmc_ios *ios);
......
......@@ -141,7 +141,6 @@ static const struct timing_data td[] = {
struct sdhci_am654_data {
struct regmap *base;
bool legacy_otapdly;
int otap_del_sel[ARRAY_SIZE(td)];
int itap_del_sel[ARRAY_SIZE(td)];
int clkbuf_sel;
......@@ -272,11 +271,7 @@ static void sdhci_am654_set_clock(struct sdhci_host *host, unsigned int clock)
sdhci_set_clock(host, clock);
/* Setup DLL Output TAP delay */
if (sdhci_am654->legacy_otapdly)
otap_del_sel = sdhci_am654->otap_del_sel[0];
else
otap_del_sel = sdhci_am654->otap_del_sel[timing];
otap_del_ena = (timing > MMC_TIMING_UHS_SDR25) ? 1 : 0;
mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
......@@ -314,9 +309,6 @@ static void sdhci_j721e_4bit_set_clock(struct sdhci_host *host,
u32 mask, val;
/* Setup DLL Output TAP delay */
if (sdhci_am654->legacy_otapdly)
otap_del_sel = sdhci_am654->otap_del_sel[0];
else
otap_del_sel = sdhci_am654->otap_del_sel[timing];
mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
......@@ -577,32 +569,15 @@ static int sdhci_am654_get_otap_delay(struct sdhci_host *host,
int i;
int ret;
ret = device_property_read_u32(dev, td[MMC_TIMING_LEGACY].otap_binding,
&sdhci_am654->otap_del_sel[MMC_TIMING_LEGACY]);
if (ret) {
/*
* ti,otap-del-sel-legacy is mandatory, look for old binding
* if not found.
*/
ret = device_property_read_u32(dev, "ti,otap-del-sel",
&sdhci_am654->otap_del_sel[0]);
if (ret) {
dev_err(dev, "Couldn't find otap-del-sel\n");
return ret;
}
dev_info(dev, "Using legacy binding ti,otap-del-sel\n");
sdhci_am654->legacy_otapdly = true;
return 0;
}
for (i = MMC_TIMING_LEGACY; i <= MMC_TIMING_MMC_HS400; i++) {
ret = device_property_read_u32(dev, td[i].otap_binding,
&sdhci_am654->otap_del_sel[i]);
if (ret) {
if (i == MMC_TIMING_LEGACY) {
dev_err(dev, "Couldn't find mandatory ti,otap-del-sel-legacy\n");
return ret;
}
dev_dbg(dev, "Couldn't find %s\n",
td[i].otap_binding);
/*
......
......@@ -32,6 +32,7 @@ struct mmc_csd {
unsigned int r2w_factor;
unsigned int max_dtr;
unsigned int erase_size; /* In sectors */
unsigned int wp_grp_size;
unsigned int read_blkbits;
unsigned int write_blkbits;
unsigned int capacity;
......@@ -52,9 +53,6 @@ struct mmc_ext_csd {
u8 part_config;
u8 cache_ctrl;
u8 rst_n_function;
u8 max_packed_writes;
u8 max_packed_reads;
u8 packed_event_en;
unsigned int part_time; /* Units: ms */
unsigned int sa_timeout; /* Units: 100ns */
unsigned int generic_cmd6_time; /* Units: 10ms */
......@@ -306,6 +304,7 @@ struct mmc_card {
unsigned int eg_boundary; /* don't cross erase-group boundaries */
unsigned int erase_arg; /* erase / trim / discard */
u8 erased_byte; /* value of erased bytes */
unsigned int wp_grp_size; /* write group size in sectors */
u32 raw_cid[4]; /* raw card CID */
u32 raw_csd[4]; /* raw card CSD */
......
......@@ -27,7 +27,6 @@ struct mmc_command {
u32 opcode;
u32 arg;
#define MMC_CMD23_ARG_REL_WR (1 << 31)
#define MMC_CMD23_ARG_PACKED ((0 << 31) | (1 << 30))
#define MMC_CMD23_ARG_TAG_REQ (1 << 29)
u32 resp[4];
unsigned int flags; /* expected response type */
......
......@@ -257,8 +257,6 @@ static inline bool mmc_ready_for_data(u32 status)
#define EXT_CSD_FLUSH_CACHE 32 /* W */
#define EXT_CSD_CACHE_CTRL 33 /* R/W */
#define EXT_CSD_POWER_OFF_NOTIFICATION 34 /* R/W */
#define EXT_CSD_PACKED_FAILURE_INDEX 35 /* RO */
#define EXT_CSD_PACKED_CMD_STATUS 36 /* RO */
#define EXT_CSD_EXP_EVENTS_STATUS 54 /* RO, 2 bytes */
#define EXT_CSD_EXP_EVENTS_CTRL 56 /* R/W, 2 bytes */
#define EXT_CSD_DATA_SECTOR_SIZE 61 /* R */
......@@ -321,8 +319,6 @@ static inline bool mmc_ready_for_data(u32 status)
#define EXT_CSD_SUPPORTED_MODE 493 /* RO */
#define EXT_CSD_TAG_UNIT_SIZE 498 /* RO */
#define EXT_CSD_DATA_TAG_SUPPORT 499 /* RO */
#define EXT_CSD_MAX_PACKED_WRITES 500 /* RO */
#define EXT_CSD_MAX_PACKED_READS 501 /* RO */
#define EXT_CSD_BKOPS_SUPPORT 502 /* RO */
#define EXT_CSD_HPI_FEATURES 503 /* RO */
......@@ -402,18 +398,12 @@ static inline bool mmc_ready_for_data(u32 status)
#define EXT_CSD_PWR_CL_8BIT_SHIFT 4
#define EXT_CSD_PWR_CL_4BIT_SHIFT 0
#define EXT_CSD_PACKED_EVENT_EN BIT(3)
/*
* EXCEPTION_EVENT_STATUS field
*/
#define EXT_CSD_URGENT_BKOPS BIT(0)
#define EXT_CSD_DYNCAP_NEEDED BIT(1)
#define EXT_CSD_SYSPOOL_EXHAUSTED BIT(2)
#define EXT_CSD_PACKED_FAILURE BIT(3)
#define EXT_CSD_PACKED_GENERIC_ERROR BIT(0)
#define EXT_CSD_PACKED_INDEXED_ERROR BIT(1)
/*
* BKOPS status level
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment