mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-27 14:43:58 +08:00
MMC core:
- Add support for Cache Ctrl for SD cards - Add support for Power Off Notification for SD cards - Add support for read/write of the SD function extension registers - Allow broken eMMC HS400 mode to be disabled via DT - Allow UHS-I voltage switch for SDSC cards if supported - Disable command queueing in the ioctl path - Enable eMMC sleep commands to use HW busy polling to minimize delay - Extend re-use of the common polling loop to standardize behaviour - Take into account MMC_CAP_NEED_RSP_BUSY for eMMC HPI commands MMC host: - jz4740: Add support for the JZ4775 variant - sdhci-acpi: Disable write protect detection on Toshiba Encore 2 WT8-B - sdhci-esdhc-imx: Advertise HS400 support through MMC caps - sdhci-esdhc-imx: Enable support for system wakeup for SDIO - sdhci-iproc: Add support for the legacy sdhci controller on the BCM7211 - vub3000: Fix control-request direction MEMSTICK: - A couple of fixes/cleanups. -----BEGIN PGP SIGNATURE----- iQJLBAABCgA1FiEEugLDXPmKSktSkQsV/iaEJXNYjCkFAmDZoOgXHHVsZi5oYW5z c29uQGxpbmFyby5vcmcACgkQ/iaEJXNYjCm6lhAAuR2iIfcwSqDQ0i6NGT0TYtwk 02Bg1qJu2sggM+MapjVjUED4ldxvrEaHo5RVcY5yD7UZEyxDWfLrNUyuzm1h68D6 weXBWACgc2DqEV//I585i025JcfCTvUXIzXhdhRohVBPHzz5RiveqkWzTu9HrPRA urBgWdyWI2pt3pZWq1YRSR/rLE+B2JytFDBRlzjefi0JPKKNQxuLCChGgJDLMjOE sLdxzB8iVLMBZg51vgtK3vr5jfp2as8scKjZQh/QO5Xcs6NIeQOMfytBQ1mMAgV5 1F1uAb8K4ilyc3/zJlVwjRw9ZPWdm3GbNVNaq6gSfuxKjS9SdDrzgme4LwaNpBvb bSJ2ieRtAorjULNBcZlGStUtt6EAMWuSt/14XKvqUIKb+5mkPf9fJ1J5QL4rrR0t M1OYKYHaGworW8GKzFvtkSzdxwmQTg8qAD+l1zSdBU8q55Ok6tllKI8nBNikI3Rv dy2+wAWua5P3kgXCeRP7FFdg0FVhKr1HwiPnE7pBB1axkUkj5J5/oTFwUwcfrITD YUemlGaTGZ9wQfuoqBy+kqAS1w03j4d0Yts9/5KW/B/xpaSVLuBLwe4R6a267rRl zi+jNH0rpRIyJoE3+Zn29X8viDd9o27gmYe7p9YFEIbRy6qLQwIeWIaJ5kDjAaAR uO9n9sIvxkeHYIsWcZM= =zUwA -----END PGP SIGNATURE----- Merge tag 'mmc-v5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc Pull MMC and MEMSTICK updates from Ulf Hansson: "MMC core: - Add support for Cache Ctrl for SD cards - Add support for Power Off Notification for SD cards - Add support for read/write of the SD function extension registers - Allow broken eMMC HS400 mode to be disabled via DT - Allow UHS-I voltage switch for SDSC cards if supported - Disable command queueing in the ioctl path - Enable eMMC sleep commands to use HW busy polling to minimize delay - Extend re-use of the common polling loop to standardize behaviour - Take into account MMC_CAP_NEED_RSP_BUSY for eMMC HPI commands MMC host: - jz4740: Add support for the JZ4775 variant - sdhci-acpi: Disable write protect detection on Toshiba Encore 2 WT8-B - sdhci-esdhc-imx: Advertise HS400 support through MMC caps - sdhci-esdhc-imx: Enable support for system wakeup for SDIO - sdhci-iproc: Add support for the legacy sdhci controller on the BCM7211 - vub3000: Fix control-request direction MEMSTICK: - A couple of fixes/cleanups" * tag 'mmc-v5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: (54 commits) mmc: sdhci-iproc: Add support for the legacy sdhci controller on the BCM7211 dt-bindings: mmc: sdhci-iproc: Add brcm,bcm7211a0-sdhci mmc: JZ4740: Add support for JZ4775 dt-bindings: mmc: JZ4740: Add bindings for JZ4775 mmc: sdhci-esdhc-imx: Enable support for system wakeup for SDIO mmc: Improve function name when aborting a tuning cmd mmc: sdhci-of-aspeed: Turn down a phase correction warning mmc: debugfs: add description for module parameter mmc: via-sdmmc: add a check against NULL pointer dereference mmc: sdhci-sprd: use sdhci_sprd_writew mmc: sdhci-esdhc-imx: remove unused is_imx6q_usdhc mmc: core: Allow UHS-I voltage switch for SDSC cards if supported mmc: mmc_spi: Imply container_of() to be no-op mmc: mmc_spi: Drop duplicate 'mmc_spi' in the debug messages mmc: dw_mmc-pltfm: Remove unused <linux/clk.h> mmc: sdhci-of-aspeed: Configure the SDHCIs as specified by the devicetree. mmc: core: Add a missing SPDX license header mmc: vub3000: fix control-request direction mmc: sdhci-omap: Use pm_runtime_resume_and_get() to replace open coding mmc: sdhci_am654: Use pm_runtime_resume_and_get() to replace open coding ...
This commit is contained in:
commit
ef60eb0eb6
@ -21,6 +21,7 @@ properties:
|
||||
- brcm,bcm2711-emmc2
|
||||
- brcm,sdhci-iproc-cygnus
|
||||
- brcm,sdhci-iproc
|
||||
- brcm,bcm7211a0-sdhci
|
||||
|
||||
reg:
|
||||
minItems: 1
|
||||
|
@ -19,6 +19,7 @@ properties:
|
||||
- ingenic,jz4740-mmc
|
||||
- ingenic,jz4725b-mmc
|
||||
- ingenic,jz4760-mmc
|
||||
- ingenic,jz4775-mmc
|
||||
- ingenic,jz4780-mmc
|
||||
- ingenic,x1000-mmc
|
||||
- items:
|
||||
|
@ -220,6 +220,11 @@ properties:
|
||||
description:
|
||||
eMMC HS400 enhanced strobe mode is supported
|
||||
|
||||
no-mmc-hs400:
|
||||
$ref: /schemas/types.yaml#/definitions/flag
|
||||
description:
|
||||
All eMMC HS400 modes are not supported.
|
||||
|
||||
dsr:
|
||||
description:
|
||||
Value the card Driver Stage Register (DSR) should be programmed
|
||||
@ -357,22 +362,6 @@ dependencies:
|
||||
additionalProperties: true
|
||||
|
||||
examples:
|
||||
- |
|
||||
mmc@ab000000 {
|
||||
compatible = "sdhci";
|
||||
reg = <0xab000000 0x200>;
|
||||
interrupts = <23>;
|
||||
bus-width = <4>;
|
||||
cd-gpios = <&gpio 69 0>;
|
||||
cd-inverted;
|
||||
wp-gpios = <&gpio 70 0>;
|
||||
max-frequency = <50000000>;
|
||||
keep-power-in-suspend;
|
||||
wakeup-source;
|
||||
mmc-pwrseq = <&sdhci0_pwrseq>;
|
||||
clk-phase-sd-hs = <63>, <72>;
|
||||
};
|
||||
|
||||
- |
|
||||
mmc3: mmc@1c12000 {
|
||||
#address-cells = <1>;
|
||||
@ -385,9 +374,9 @@ examples:
|
||||
non-removable;
|
||||
mmc-pwrseq = <&sdhci0_pwrseq>;
|
||||
|
||||
brcmf: bcrmf@1 {
|
||||
brcmf: wifi@1 {
|
||||
reg = <1>;
|
||||
compatible = "brcm,bcm43xx-fmac";
|
||||
compatible = "brcm,bcm4329-fmac";
|
||||
interrupt-parent = <&pio>;
|
||||
interrupts = <10 8>;
|
||||
interrupt-names = "host-wake";
|
||||
|
@ -1,53 +0,0 @@
|
||||
* Renesas Multi Media Card Interface (MMCIF) Controller
|
||||
|
||||
This file documents differences between the core properties in mmc.txt
|
||||
and the properties used by the MMCIF device.
|
||||
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: should be "renesas,mmcif-<soctype>", "renesas,sh-mmcif" as a
|
||||
fallback. Examples with <soctype> are:
|
||||
- "renesas,mmcif-r7s72100" for the MMCIF found in r7s72100 SoCs
|
||||
- "renesas,mmcif-r8a73a4" for the MMCIF found in r8a73a4 SoCs
|
||||
- "renesas,mmcif-r8a7740" for the MMCIF found in r8a7740 SoCs
|
||||
- "renesas,mmcif-r8a7742" for the MMCIF found in r8a7742 SoCs
|
||||
- "renesas,mmcif-r8a7743" for the MMCIF found in r8a7743 SoCs
|
||||
- "renesas,mmcif-r8a7744" for the MMCIF found in r8a7744 SoCs
|
||||
- "renesas,mmcif-r8a7745" for the MMCIF found in r8a7745 SoCs
|
||||
- "renesas,mmcif-r8a7778" for the MMCIF found in r8a7778 SoCs
|
||||
- "renesas,mmcif-r8a7790" for the MMCIF found in r8a7790 SoCs
|
||||
- "renesas,mmcif-r8a7791" for the MMCIF found in r8a7791 SoCs
|
||||
- "renesas,mmcif-r8a7793" for the MMCIF found in r8a7793 SoCs
|
||||
- "renesas,mmcif-r8a7794" for the MMCIF found in r8a7794 SoCs
|
||||
- "renesas,mmcif-sh73a0" for the MMCIF found in sh73a0 SoCs
|
||||
|
||||
- interrupts: Some SoCs have only 1 shared interrupt, while others have either
|
||||
2 or 3 individual interrupts (error, int, card detect). Below is the number
|
||||
of interrupts for each SoC:
|
||||
1: r8a73a4, r8a7742, r8a7743, r8a7744, r8a7745, r8a7778, r8a7790, r8a7791,
|
||||
r8a7793, r8a7794
|
||||
2: r8a7740, sh73a0
|
||||
3: r7s72100
|
||||
|
||||
- clocks: reference to the functional clock
|
||||
|
||||
- dmas: reference to the DMA channels, one per channel name listed in the
|
||||
dma-names property.
|
||||
- dma-names: must contain "tx" for the transmit DMA channel and "rx" for the
|
||||
receive DMA channel.
|
||||
- max-frequency: Maximum operating clock frequency, driver uses default clock
|
||||
frequency if it is not set.
|
||||
|
||||
|
||||
Example: R8A7790 (R-Car H2) MMCIF0
|
||||
|
||||
mmcif0: mmc@ee200000 {
|
||||
compatible = "renesas,mmcif-r8a7790", "renesas,sh-mmcif";
|
||||
reg = <0 0xee200000 0 0x80>;
|
||||
interrupts = <0 169 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&mstp3_clks R8A7790_CLK_MMCIF0>;
|
||||
dmas = <&dmac0 0xd1>, <&dmac0 0xd2>;
|
||||
dma-names = "tx", "rx";
|
||||
max-frequency = <97500000>;
|
||||
};
|
135
Documentation/devicetree/bindings/mmc/renesas,mmcif.yaml
Normal file
135
Documentation/devicetree/bindings/mmc/renesas,mmcif.yaml
Normal file
@ -0,0 +1,135 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mmc/renesas,mmcif.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas Multi Media Card Interface (MMCIF) Controller
|
||||
|
||||
maintainers:
|
||||
- Wolfram Sang <wsa+renesas@sang-engineering.com>
|
||||
|
||||
allOf:
|
||||
- $ref: "mmc-controller.yaml"
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- renesas,mmcif-r7s72100 # RZ/A1H
|
||||
- renesas,mmcif-r8a73a4 # R-Mobile APE6
|
||||
- renesas,mmcif-r8a7740 # R-Mobile A1
|
||||
- renesas,mmcif-r8a7742 # RZ/G1H
|
||||
- renesas,mmcif-r8a7743 # RZ/G1M
|
||||
- renesas,mmcif-r8a7744 # RZ/G1N
|
||||
- renesas,mmcif-r8a7745 # RZ/G1E
|
||||
- renesas,mmcif-r8a7778 # R-Car M1A
|
||||
- renesas,mmcif-r8a7790 # R-Car H2
|
||||
- renesas,mmcif-r8a7791 # R-Car M2-W
|
||||
- renesas,mmcif-r8a7793 # R-Car M2-N
|
||||
- renesas,mmcif-r8a7794 # R-Car E2
|
||||
- renesas,mmcif-sh73a0 # SH-Mobile AG5
|
||||
- const: renesas,sh-mmcif
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts: true
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
dmas:
|
||||
minItems: 2
|
||||
maxItems: 4
|
||||
description:
|
||||
Must contain a list of pairs of references to DMA specifiers, one for
|
||||
transmission, and one for reception.
|
||||
|
||||
dma-names:
|
||||
minItems: 2
|
||||
maxItems: 4
|
||||
items:
|
||||
enum:
|
||||
- tx
|
||||
- rx
|
||||
|
||||
max-frequency: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- power-domains
|
||||
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: renesas,mmcif-r7s72100
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
items:
|
||||
- description: Error interrupt
|
||||
- description: Normal operation interrupt
|
||||
- description: Card detection interrupt
|
||||
else:
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- renesas,mmcif-r8a7740
|
||||
- renesas,mmcif-sh73a0
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
items:
|
||||
- description: Error interrupt
|
||||
- description: Normal operation interrupt
|
||||
else:
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- renesas,mmcif-r8a73a4
|
||||
- renesas,mmcif-r8a7778
|
||||
then:
|
||||
properties:
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
else:
|
||||
properties:
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
required:
|
||||
- resets
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/r8a7790-cpg-mssr.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/power/r8a7790-sysc.h>
|
||||
|
||||
mmcif0: mmc@ee200000 {
|
||||
compatible = "renesas,mmcif-r8a7790", "renesas,sh-mmcif";
|
||||
reg = <0xee200000 0x80>;
|
||||
interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&cpg CPG_MOD 315>;
|
||||
power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
|
||||
resets = <&cpg 315>;
|
||||
dmas = <&dmac0 0xd1>, <&dmac0 0xd2>, <&dmac1 0xd1>, <&dmac1 0xd2>;
|
||||
dma-names = "tx", "rx", "tx", "rx";
|
||||
max-frequency = <97500000>;
|
||||
};
|
@ -29,21 +29,15 @@ properties:
|
||||
- const: rockchip,rk3288-dw-mshc
|
||||
- items:
|
||||
- enum:
|
||||
# for Rockchip PX30
|
||||
- rockchip,px30-dw-mshc
|
||||
# for Rockchip RK3036
|
||||
- rockchip,rk1808-dw-mshc
|
||||
- rockchip,rk3036-dw-mshc
|
||||
# for Rockchip RK322x
|
||||
- rockchip,rk3228-dw-mshc
|
||||
# for Rockchip RK3308
|
||||
- rockchip,rk3308-dw-mshc
|
||||
# for Rockchip RK3328
|
||||
- rockchip,rk3328-dw-mshc
|
||||
# for Rockchip RK3368
|
||||
- rockchip,rk3368-dw-mshc
|
||||
# for Rockchip RK3399
|
||||
- rockchip,rk3399-dw-mshc
|
||||
# for Rockchip RV1108
|
||||
- rockchip,rk3568-dw-mshc
|
||||
- rockchip,rv1108-dw-mshc
|
||||
- const: rockchip,rk3288-dw-mshc
|
||||
|
||||
|
@ -19,7 +19,6 @@ properties:
|
||||
- const: ti,am654-sdhci-5.1
|
||||
- const: ti,j721e-sdhci-8bit
|
||||
- const: ti,j721e-sdhci-4bit
|
||||
- const: ti,j721e-sdhci-4bit
|
||||
- const: ti,am64-sdhci-8bit
|
||||
- const: ti,am64-sdhci-4bit
|
||||
- items:
|
||||
|
@ -129,7 +129,7 @@ static int msb_sg_compare_to_buffer(struct scatterlist *sg,
|
||||
* Each zone consists of 512 eraseblocks, out of which in first
|
||||
* zone 494 are used and 496 are for all following zones.
|
||||
* Therefore zone #0 hosts blocks 0-493, zone #1 blocks 494-988, etc...
|
||||
*/
|
||||
*/
|
||||
static int msb_get_zone_from_lba(int lba)
|
||||
{
|
||||
if (lba < 494)
|
||||
@ -348,8 +348,9 @@ again:
|
||||
switch (msb->state) {
|
||||
case MSB_RP_SEND_BLOCK_ADDRESS:
|
||||
/* msb_write_regs sometimes "fails" because it needs to update
|
||||
the reg window, and thus it returns request for that.
|
||||
Then we stay in this state and retry */
|
||||
* the reg window, and thus it returns request for that.
|
||||
* Then we stay in this state and retry
|
||||
*/
|
||||
if (!msb_write_regs(msb,
|
||||
offsetof(struct ms_register, param),
|
||||
sizeof(struct ms_param_register),
|
||||
@ -368,7 +369,8 @@ again:
|
||||
case MSB_RP_SEND_INT_REQ:
|
||||
msb->state = MSB_RP_RECEIVE_INT_REQ_RESULT;
|
||||
/* If dont actually need to send the int read request (only in
|
||||
serial mode), then just fall through */
|
||||
* serial mode), then just fall through
|
||||
*/
|
||||
if (msb_read_int_reg(msb, -1))
|
||||
return 0;
|
||||
fallthrough;
|
||||
@ -702,7 +704,8 @@ static int h_msb_parallel_switch(struct memstick_dev *card,
|
||||
|
||||
case MSB_PS_SWICH_HOST:
|
||||
/* Set parallel interface on our side + send a dummy request
|
||||
to see if card responds */
|
||||
* to see if card responds
|
||||
*/
|
||||
host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PAR4);
|
||||
memstick_init_req(mrq, MS_TPC_GET_INT, NULL, 1);
|
||||
msb->state = MSB_PS_CONFIRM;
|
||||
@ -821,6 +824,7 @@ static int msb_mark_page_bad(struct msb_data *msb, int pba, int page)
|
||||
static int msb_erase_block(struct msb_data *msb, u16 pba)
|
||||
{
|
||||
int error, try;
|
||||
|
||||
if (msb->read_only)
|
||||
return -EROFS;
|
||||
|
||||
@ -997,6 +1001,7 @@ static int msb_write_block(struct msb_data *msb,
|
||||
u16 pba, u32 lba, struct scatterlist *sg, int offset)
|
||||
{
|
||||
int error, current_try = 1;
|
||||
|
||||
BUG_ON(sg->length < msb->page_size);
|
||||
|
||||
if (msb->read_only)
|
||||
@ -1045,11 +1050,12 @@ static int msb_write_block(struct msb_data *msb,
|
||||
error = msb_run_state_machine(msb, h_msb_write_block);
|
||||
|
||||
/* Sector we just wrote to is assumed erased since its pba
|
||||
was erased. If it wasn't erased, write will succeed
|
||||
and will just clear the bits that were set in the block
|
||||
thus test that what we have written,
|
||||
matches what we expect.
|
||||
We do trust the blocks that we erased */
|
||||
* was erased. If it wasn't erased, write will succeed
|
||||
* and will just clear the bits that were set in the block
|
||||
* thus test that what we have written,
|
||||
* matches what we expect.
|
||||
* We do trust the blocks that we erased
|
||||
*/
|
||||
if (!error && (verify_writes ||
|
||||
!test_bit(pba, msb->erased_blocks_bitmap)))
|
||||
error = msb_verify_block(msb, pba, sg, offset);
|
||||
@ -1493,6 +1499,7 @@ static int msb_ftl_scan(struct msb_data *msb)
|
||||
static void msb_cache_flush_timer(struct timer_list *t)
|
||||
{
|
||||
struct msb_data *msb = from_timer(msb, t, cache_flush_timer);
|
||||
|
||||
msb->need_flush_cache = true;
|
||||
queue_work(msb->io_queue, &msb->io_work);
|
||||
}
|
||||
@ -1673,7 +1680,8 @@ static int msb_cache_read(struct msb_data *msb, int lba,
|
||||
* This table content isn't that importaint,
|
||||
* One could put here different values, providing that they still
|
||||
* cover whole disk.
|
||||
* 64 MB entry is what windows reports for my 64M memstick */
|
||||
* 64 MB entry is what windows reports for my 64M memstick
|
||||
*/
|
||||
|
||||
static const struct chs_entry chs_table[] = {
|
||||
/* size sectors cylynders heads */
|
||||
@ -1706,8 +1714,9 @@ static int msb_init_card(struct memstick_dev *card)
|
||||
return error;
|
||||
|
||||
/* Due to a bug in Jmicron driver written by Alex Dubov,
|
||||
its serial mode barely works,
|
||||
so we switch to parallel mode right away */
|
||||
* its serial mode barely works,
|
||||
* so we switch to parallel mode right away
|
||||
*/
|
||||
if (host->caps & MEMSTICK_CAP_PAR4)
|
||||
msb_switch_to_parallel(msb);
|
||||
|
||||
@ -2033,6 +2042,7 @@ static blk_status_t msb_queue_rq(struct blk_mq_hw_ctx *hctx,
|
||||
static int msb_check_card(struct memstick_dev *card)
|
||||
{
|
||||
struct msb_data *msb = memstick_get_drvdata(card);
|
||||
|
||||
return (msb->card_dead == 0);
|
||||
}
|
||||
|
||||
@ -2333,6 +2343,7 @@ static struct memstick_driver msb_driver = {
|
||||
static int __init msb_init(void)
|
||||
{
|
||||
int rc = memstick_register_driver(&msb_driver);
|
||||
|
||||
if (rc)
|
||||
pr_err("failed to register memstick driver (error %d)\n", rc);
|
||||
|
||||
|
@ -799,9 +799,9 @@ static int rtsx_usb_ms_drv_probe(struct platform_device *pdev)
|
||||
|
||||
return 0;
|
||||
err_out:
|
||||
memstick_free_host(msh);
|
||||
pm_runtime_disable(ms_dev(host));
|
||||
pm_runtime_put_noidle(ms_dev(host));
|
||||
memstick_free_host(msh);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -828,9 +828,6 @@ static int rtsx_usb_ms_drv_remove(struct platform_device *pdev)
|
||||
}
|
||||
mutex_unlock(&host->host_mutex);
|
||||
|
||||
memstick_remove_host(msh);
|
||||
memstick_free_host(msh);
|
||||
|
||||
/* Balance possible unbalanced usage count
|
||||
* e.g. unconditional module removal
|
||||
*/
|
||||
@ -838,10 +835,11 @@ static int rtsx_usb_ms_drv_remove(struct platform_device *pdev)
|
||||
pm_runtime_put(ms_dev(host));
|
||||
|
||||
pm_runtime_disable(ms_dev(host));
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
memstick_remove_host(msh);
|
||||
dev_dbg(ms_dev(host),
|
||||
": Realtek USB Memstick controller has been removed\n");
|
||||
memstick_free_host(msh);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Block driver for media (i.e., flash cards)
|
||||
*
|
||||
@ -1004,6 +1005,12 @@ 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 (ret)
|
||||
break;
|
||||
}
|
||||
fallthrough;
|
||||
case MMC_DRV_OP_IOCTL_RPMB:
|
||||
idata = mq_rq->drv_op_data;
|
||||
for (i = 0, ret = 0; i < mq_rq->ioc_count; i++) {
|
||||
@ -1014,6 +1021,8 @@ 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);
|
||||
break;
|
||||
case MMC_DRV_OP_BOOT_WP:
|
||||
ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP,
|
||||
@ -1159,7 +1168,7 @@ static void mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req)
|
||||
struct mmc_card *card = md->queue.card;
|
||||
int ret = 0;
|
||||
|
||||
ret = mmc_flush_cache(card);
|
||||
ret = mmc_flush_cache(card->host);
|
||||
blk_mq_end_request(req, ret ? BLK_STS_IOERR : BLK_STS_OK);
|
||||
}
|
||||
|
||||
|
@ -1582,7 +1582,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
|
||||
{
|
||||
struct mmc_command cmd = {};
|
||||
unsigned int qty = 0, busy_timeout = 0;
|
||||
bool use_r1b_resp = false;
|
||||
bool use_r1b_resp;
|
||||
int err;
|
||||
|
||||
mmc_retune_hold(card->host);
|
||||
@ -1650,23 +1650,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
|
||||
cmd.opcode = MMC_ERASE;
|
||||
cmd.arg = arg;
|
||||
busy_timeout = mmc_erase_timeout(card, arg, qty);
|
||||
/*
|
||||
* If the host controller supports busy signalling and the timeout for
|
||||
* the erase operation does not exceed the max_busy_timeout, we should
|
||||
* use R1B response. Or we need to prevent the host from doing hw busy
|
||||
* detection, which is done by converting to a R1 response instead.
|
||||
* Note, some hosts requires R1B, which also means they are on their own
|
||||
* when it comes to deal with the busy timeout.
|
||||
*/
|
||||
if (!(card->host->caps & MMC_CAP_NEED_RSP_BUSY) &&
|
||||
card->host->max_busy_timeout &&
|
||||
busy_timeout > card->host->max_busy_timeout) {
|
||||
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
|
||||
} else {
|
||||
cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
|
||||
cmd.busy_timeout = busy_timeout;
|
||||
use_r1b_resp = true;
|
||||
}
|
||||
use_r1b_resp = mmc_prepare_busy_cmd(card->host, &cmd, busy_timeout);
|
||||
|
||||
err = mmc_wait_for_cmd(card->host, &cmd, 0);
|
||||
if (err) {
|
||||
@ -1687,7 +1671,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
|
||||
goto out;
|
||||
|
||||
/* Let's poll to find out when the erase operation completes. */
|
||||
err = mmc_poll_for_busy(card, busy_timeout, MMC_BUSY_ERASE);
|
||||
err = mmc_poll_for_busy(card, busy_timeout, false, MMC_BUSY_ERASE);
|
||||
|
||||
out:
|
||||
mmc_retune_release(card->host);
|
||||
|
@ -30,6 +30,7 @@ struct mmc_bus_ops {
|
||||
int (*hw_reset)(struct mmc_host *);
|
||||
int (*sw_reset)(struct mmc_host *);
|
||||
bool (*cache_enabled)(struct mmc_host *);
|
||||
int (*flush_cache)(struct mmc_host *);
|
||||
};
|
||||
|
||||
void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops);
|
||||
@ -172,4 +173,12 @@ static inline bool mmc_cache_enabled(struct mmc_host *host)
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int mmc_flush_cache(struct mmc_host *host)
|
||||
{
|
||||
if (host->bus_ops->flush_cache)
|
||||
return host->bus_ops->flush_cache(host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -26,6 +26,7 @@
|
||||
static DECLARE_FAULT_ATTR(fail_default_attr);
|
||||
static char *fail_request;
|
||||
module_param(fail_request, charp, 0);
|
||||
MODULE_PARM_DESC(fail_request, "default fault injection attributes");
|
||||
|
||||
#endif /* CONFIG_FAIL_MMC_REQUEST */
|
||||
|
||||
|
@ -388,6 +388,9 @@ int mmc_of_parse(struct mmc_host *host)
|
||||
host->caps2 |= MMC_CAP2_NO_SD;
|
||||
if (device_property_read_bool(dev, "no-mmc"))
|
||||
host->caps2 |= MMC_CAP2_NO_MMC;
|
||||
if (device_property_read_bool(dev, "no-mmc-hs400"))
|
||||
host->caps2 &= ~(MMC_CAP2_HS400_1_8V | MMC_CAP2_HS400_1_2V |
|
||||
MMC_CAP2_HS400_ES);
|
||||
|
||||
/* Must be after "non-removable" check */
|
||||
if (device_property_read_u32(dev, "fixed-emmc-driver-type", &drv_type) == 0) {
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
#define DEFAULT_CMD6_TIMEOUT_MS 500
|
||||
#define MIN_CACHE_EN_TIMEOUT_MS 1600
|
||||
#define CACHE_FLUSH_TIMEOUT_MS 30000 /* 30s */
|
||||
|
||||
static const unsigned int tran_exp[] = {
|
||||
10000, 100000, 1000000, 10000000,
|
||||
@ -1905,11 +1906,20 @@ static int mmc_can_sleep(struct mmc_card *card)
|
||||
return card->ext_csd.rev >= 3;
|
||||
}
|
||||
|
||||
static int mmc_sleep_busy_cb(void *cb_data, bool *busy)
|
||||
{
|
||||
struct mmc_host *host = cb_data;
|
||||
|
||||
*busy = host->ops->card_busy(host);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mmc_sleep(struct mmc_host *host)
|
||||
{
|
||||
struct mmc_command cmd = {};
|
||||
struct mmc_card *card = host->card;
|
||||
unsigned int timeout_ms = DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000);
|
||||
bool use_r1b_resp;
|
||||
int err;
|
||||
|
||||
/* Re-tuning can't be done once the card is deselected */
|
||||
@ -1922,35 +1932,27 @@ static int mmc_sleep(struct mmc_host *host)
|
||||
cmd.opcode = MMC_SLEEP_AWAKE;
|
||||
cmd.arg = card->rca << 16;
|
||||
cmd.arg |= 1 << 15;
|
||||
|
||||
/*
|
||||
* If the max_busy_timeout of the host is specified, validate it against
|
||||
* the sleep cmd timeout. A failure means we need to prevent the host
|
||||
* from doing hw busy detection, which is done by converting to a R1
|
||||
* response instead of a R1B. Note, some hosts requires R1B, which also
|
||||
* means they are on their own when it comes to deal with the busy
|
||||
* timeout.
|
||||
*/
|
||||
if (!(host->caps & MMC_CAP_NEED_RSP_BUSY) && host->max_busy_timeout &&
|
||||
(timeout_ms > host->max_busy_timeout)) {
|
||||
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
|
||||
} else {
|
||||
cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
|
||||
cmd.busy_timeout = timeout_ms;
|
||||
}
|
||||
use_r1b_resp = mmc_prepare_busy_cmd(host, &cmd, timeout_ms);
|
||||
|
||||
err = mmc_wait_for_cmd(host, &cmd, 0);
|
||||
if (err)
|
||||
goto out_release;
|
||||
|
||||
/*
|
||||
* If the host does not wait while the card signals busy, then we will
|
||||
* will have to wait the sleep/awake timeout. Note, we cannot use the
|
||||
* SEND_STATUS command to poll the status because that command (and most
|
||||
* others) is invalid while the card sleeps.
|
||||
* If the host does not wait while the card signals busy, then we can
|
||||
* try to poll, but only if the host supports HW polling, as the
|
||||
* SEND_STATUS cmd is not allowed. If we can't poll, then we simply need
|
||||
* to wait the sleep/awake timeout.
|
||||
*/
|
||||
if (!cmd.busy_timeout || !(host->caps & MMC_CAP_WAIT_WHILE_BUSY))
|
||||
if (host->caps & MMC_CAP_WAIT_WHILE_BUSY && use_r1b_resp)
|
||||
goto out_release;
|
||||
|
||||
if (!host->ops->card_busy) {
|
||||
mmc_delay(timeout_ms);
|
||||
goto out_release;
|
||||
}
|
||||
|
||||
err = __mmc_poll_for_busy(card, timeout_ms, &mmc_sleep_busy_cb, host);
|
||||
|
||||
out_release:
|
||||
mmc_retune_release(host);
|
||||
@ -2035,6 +2037,25 @@ static bool _mmc_cache_enabled(struct mmc_host *host)
|
||||
host->card->ext_csd.cache_ctrl & 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush the internal cache of the eMMC to non-volatile storage.
|
||||
*/
|
||||
static int _mmc_flush_cache(struct mmc_host *host)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (_mmc_cache_enabled(host)) {
|
||||
err = mmc_switch(host->card, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_FLUSH_CACHE, 1,
|
||||
CACHE_FLUSH_TIMEOUT_MS);
|
||||
if (err)
|
||||
pr_err("%s: cache flush error %d\n",
|
||||
mmc_hostname(host), err);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
|
||||
{
|
||||
int err = 0;
|
||||
@ -2046,7 +2067,7 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
|
||||
if (mmc_card_suspended(host->card))
|
||||
goto out;
|
||||
|
||||
err = mmc_flush_cache(host->card);
|
||||
err = _mmc_flush_cache(host);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@ -2187,7 +2208,7 @@ static int _mmc_hw_reset(struct mmc_host *host)
|
||||
* In the case of recovery, we can't expect flushing the cache to work
|
||||
* always, but we have a go and ignore errors.
|
||||
*/
|
||||
mmc_flush_cache(host->card);
|
||||
_mmc_flush_cache(host);
|
||||
|
||||
if ((host->caps & MMC_CAP_HW_RESET) && host->ops->hw_reset &&
|
||||
mmc_can_reset(card)) {
|
||||
@ -2215,6 +2236,7 @@ static const struct mmc_bus_ops mmc_ops = {
|
||||
.shutdown = mmc_shutdown,
|
||||
.hw_reset = _mmc_hw_reset,
|
||||
.cache_enabled = _mmc_cache_enabled,
|
||||
.flush_cache = _mmc_flush_cache,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "mmc_ops.h"
|
||||
|
||||
#define MMC_BKOPS_TIMEOUT_MS (120 * 1000) /* 120s */
|
||||
#define MMC_CACHE_FLUSH_TIMEOUT_MS (30 * 1000) /* 30s */
|
||||
#define MMC_SANITIZE_TIMEOUT_MS (240 * 1000) /* 240s */
|
||||
|
||||
static const u8 tuning_blk_pattern_4bit[] = {
|
||||
@ -53,6 +52,12 @@ static const u8 tuning_blk_pattern_8bit[] = {
|
||||
0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee,
|
||||
};
|
||||
|
||||
struct mmc_busy_data {
|
||||
struct mmc_card *card;
|
||||
bool retry_crc_err;
|
||||
enum mmc_busy_cmd busy_cmd;
|
||||
};
|
||||
|
||||
int __mmc_send_status(struct mmc_card *card, u32 *status, unsigned int retries)
|
||||
{
|
||||
int err;
|
||||
@ -246,9 +251,8 @@ mmc_send_cxd_native(struct mmc_host *host, u32 arg, u32 *cxd, int opcode)
|
||||
* NOTE: void *buf, caller for the buf is required to use DMA-capable
|
||||
* buffer or on-stack buffer (with some overhead in callee).
|
||||
*/
|
||||
static int
|
||||
mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
|
||||
u32 opcode, void *buf, unsigned len)
|
||||
int mmc_send_adtc_data(struct mmc_card *card, struct mmc_host *host, u32 opcode,
|
||||
u32 args, void *buf, unsigned len)
|
||||
{
|
||||
struct mmc_request mrq = {};
|
||||
struct mmc_command cmd = {};
|
||||
@ -259,7 +263,7 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host,
|
||||
mrq.data = &data;
|
||||
|
||||
cmd.opcode = opcode;
|
||||
cmd.arg = 0;
|
||||
cmd.arg = args;
|
||||
|
||||
/* NOTE HACK: the MMC_RSP_SPI_R1 is always correct here, but we
|
||||
* rely on callers to never use this with "native" calls for reading
|
||||
@ -305,7 +309,7 @@ static int mmc_spi_send_cxd(struct mmc_host *host, u32 *cxd, u32 opcode)
|
||||
if (!cxd_tmp)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = mmc_send_cxd_data(NULL, host, opcode, cxd_tmp, 16);
|
||||
ret = mmc_send_adtc_data(NULL, host, opcode, 0, cxd_tmp, 16);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
@ -353,7 +357,7 @@ int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd)
|
||||
if (!ext_csd)
|
||||
return -ENOMEM;
|
||||
|
||||
err = mmc_send_cxd_data(card, card->host, MMC_SEND_EXT_CSD, ext_csd,
|
||||
err = mmc_send_adtc_data(card, card->host, MMC_SEND_EXT_CSD, 0, ext_csd,
|
||||
512);
|
||||
if (err)
|
||||
kfree(ext_csd);
|
||||
@ -424,10 +428,10 @@ int mmc_switch_status(struct mmc_card *card, bool crc_err_fatal)
|
||||
return mmc_switch_status_error(card->host, status);
|
||||
}
|
||||
|
||||
static int mmc_busy_status(struct mmc_card *card, bool retry_crc_err,
|
||||
enum mmc_busy_cmd busy_cmd, bool *busy)
|
||||
static int mmc_busy_cb(void *cb_data, bool *busy)
|
||||
{
|
||||
struct mmc_host *host = card->host;
|
||||
struct mmc_busy_data *data = cb_data;
|
||||
struct mmc_host *host = data->card->host;
|
||||
u32 status = 0;
|
||||
int err;
|
||||
|
||||
@ -436,22 +440,23 @@ static int mmc_busy_status(struct mmc_card *card, bool retry_crc_err,
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = mmc_send_status(card, &status);
|
||||
if (retry_crc_err && err == -EILSEQ) {
|
||||
err = mmc_send_status(data->card, &status);
|
||||
if (data->retry_crc_err && err == -EILSEQ) {
|
||||
*busy = true;
|
||||
return 0;
|
||||
}
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
switch (busy_cmd) {
|
||||
switch (data->busy_cmd) {
|
||||
case MMC_BUSY_CMD6:
|
||||
err = mmc_switch_status_error(card->host, status);
|
||||
err = mmc_switch_status_error(host, status);
|
||||
break;
|
||||
case MMC_BUSY_ERASE:
|
||||
err = R1_STATUS(status) ? -EIO : 0;
|
||||
break;
|
||||
case MMC_BUSY_HPI:
|
||||
case MMC_BUSY_EXTR_SINGLE:
|
||||
break;
|
||||
default:
|
||||
err = -EINVAL;
|
||||
@ -464,9 +469,9 @@ static int mmc_busy_status(struct mmc_card *card, bool retry_crc_err,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
|
||||
bool send_status, bool retry_crc_err,
|
||||
enum mmc_busy_cmd busy_cmd)
|
||||
int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
|
||||
int (*busy_cb)(void *cb_data, bool *busy),
|
||||
void *cb_data)
|
||||
{
|
||||
struct mmc_host *host = card->host;
|
||||
int err;
|
||||
@ -475,16 +480,6 @@ static int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
|
||||
bool expired = false;
|
||||
bool busy = false;
|
||||
|
||||
/*
|
||||
* In cases when not allowed to poll by using CMD13 or because we aren't
|
||||
* capable of polling by using ->card_busy(), then rely on waiting the
|
||||
* stated timeout to be sufficient.
|
||||
*/
|
||||
if (!send_status && !host->ops->card_busy) {
|
||||
mmc_delay(timeout_ms);
|
||||
return 0;
|
||||
}
|
||||
|
||||
timeout = jiffies + msecs_to_jiffies(timeout_ms) + 1;
|
||||
do {
|
||||
/*
|
||||
@ -493,7 +488,7 @@ static int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
|
||||
*/
|
||||
expired = time_after(jiffies, timeout);
|
||||
|
||||
err = mmc_busy_status(card, retry_crc_err, busy_cmd, &busy);
|
||||
err = (*busy_cb)(cb_data, &busy);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@ -516,9 +511,36 @@ static int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
|
||||
}
|
||||
|
||||
int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
|
||||
enum mmc_busy_cmd busy_cmd)
|
||||
bool retry_crc_err, enum mmc_busy_cmd busy_cmd)
|
||||
{
|
||||
return __mmc_poll_for_busy(card, timeout_ms, true, false, busy_cmd);
|
||||
struct mmc_busy_data cb_data;
|
||||
|
||||
cb_data.card = card;
|
||||
cb_data.retry_crc_err = retry_crc_err;
|
||||
cb_data.busy_cmd = busy_cmd;
|
||||
|
||||
return __mmc_poll_for_busy(card, timeout_ms, &mmc_busy_cb, &cb_data);
|
||||
}
|
||||
|
||||
bool mmc_prepare_busy_cmd(struct mmc_host *host, struct mmc_command *cmd,
|
||||
unsigned int timeout_ms)
|
||||
{
|
||||
/*
|
||||
* If the max_busy_timeout of the host is specified, make sure it's
|
||||
* enough to fit the used timeout_ms. In case it's not, let's instruct
|
||||
* the host to avoid HW busy detection, by converting to a R1 response
|
||||
* instead of a R1B. Note, some hosts requires R1B, which also means
|
||||
* they are on their own when it comes to deal with the busy timeout.
|
||||
*/
|
||||
if (!(host->caps & MMC_CAP_NEED_RSP_BUSY) && host->max_busy_timeout &&
|
||||
(timeout_ms > host->max_busy_timeout)) {
|
||||
cmd->flags = MMC_CMD_AC | MMC_RSP_SPI_R1 | MMC_RSP_R1;
|
||||
return false;
|
||||
}
|
||||
|
||||
cmd->flags = MMC_CMD_AC | MMC_RSP_SPI_R1B | MMC_RSP_R1B;
|
||||
cmd->busy_timeout = timeout_ms;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -543,7 +565,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
|
||||
struct mmc_host *host = card->host;
|
||||
int err;
|
||||
struct mmc_command cmd = {};
|
||||
bool use_r1b_resp = true;
|
||||
bool use_r1b_resp;
|
||||
unsigned char old_timing = host->ios.timing;
|
||||
|
||||
mmc_retune_hold(host);
|
||||
@ -554,29 +576,12 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
|
||||
timeout_ms = card->ext_csd.generic_cmd6_time;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the max_busy_timeout of the host is specified, make sure it's
|
||||
* enough to fit the used timeout_ms. In case it's not, let's instruct
|
||||
* the host to avoid HW busy detection, by converting to a R1 response
|
||||
* instead of a R1B. Note, some hosts requires R1B, which also means
|
||||
* they are on their own when it comes to deal with the busy timeout.
|
||||
*/
|
||||
if (!(host->caps & MMC_CAP_NEED_RSP_BUSY) && host->max_busy_timeout &&
|
||||
(timeout_ms > host->max_busy_timeout))
|
||||
use_r1b_resp = false;
|
||||
|
||||
cmd.opcode = MMC_SWITCH;
|
||||
cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
|
||||
(index << 16) |
|
||||
(value << 8) |
|
||||
set;
|
||||
cmd.flags = MMC_CMD_AC;
|
||||
if (use_r1b_resp) {
|
||||
cmd.flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B;
|
||||
cmd.busy_timeout = timeout_ms;
|
||||
} else {
|
||||
cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1;
|
||||
}
|
||||
use_r1b_resp = mmc_prepare_busy_cmd(host, &cmd, timeout_ms);
|
||||
|
||||
err = mmc_wait_for_cmd(host, &cmd, retries);
|
||||
if (err)
|
||||
@ -587,9 +592,18 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
|
||||
mmc_host_is_spi(host))
|
||||
goto out_tim;
|
||||
|
||||
/*
|
||||
* If the host doesn't support HW polling via the ->card_busy() ops and
|
||||
* when it's not allowed to poll by using CMD13, then we need to rely on
|
||||
* waiting the stated timeout to be sufficient.
|
||||
*/
|
||||
if (!send_status && !host->ops->card_busy) {
|
||||
mmc_delay(timeout_ms);
|
||||
goto out_tim;
|
||||
}
|
||||
|
||||
/* Let's try to poll to find out when the command is completed. */
|
||||
err = __mmc_poll_for_busy(card, timeout_ms, send_status, retry_crc_err,
|
||||
MMC_BUSY_CMD6);
|
||||
err = mmc_poll_for_busy(card, timeout_ms, retry_crc_err, MMC_BUSY_CMD6);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@ -686,7 +700,7 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mmc_send_tuning);
|
||||
|
||||
int mmc_abort_tuning(struct mmc_host *host, u32 opcode)
|
||||
int mmc_send_abort_tuning(struct mmc_host *host, u32 opcode)
|
||||
{
|
||||
struct mmc_command cmd = {};
|
||||
|
||||
@ -709,7 +723,7 @@ int mmc_abort_tuning(struct mmc_host *host, u32 opcode)
|
||||
|
||||
return mmc_wait_for_cmd(host, &cmd, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mmc_abort_tuning);
|
||||
EXPORT_SYMBOL_GPL(mmc_send_abort_tuning);
|
||||
|
||||
static int
|
||||
mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode,
|
||||
@ -813,28 +827,17 @@ static int mmc_send_hpi_cmd(struct mmc_card *card)
|
||||
{
|
||||
unsigned int busy_timeout_ms = card->ext_csd.out_of_int_time;
|
||||
struct mmc_host *host = card->host;
|
||||
bool use_r1b_resp = true;
|
||||
bool use_r1b_resp = false;
|
||||
struct mmc_command cmd = {};
|
||||
int err;
|
||||
|
||||
cmd.opcode = card->ext_csd.hpi_cmd;
|
||||
cmd.arg = card->rca << 16 | 1;
|
||||
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
|
||||
|
||||
/*
|
||||
* Make sure the host's max_busy_timeout fit the needed timeout for HPI.
|
||||
* In case it doesn't, let's instruct the host to avoid HW busy
|
||||
* detection, by using a R1 response instead of R1B.
|
||||
*/
|
||||
if (host->max_busy_timeout && busy_timeout_ms > host->max_busy_timeout)
|
||||
use_r1b_resp = false;
|
||||
|
||||
if (cmd.opcode == MMC_STOP_TRANSMISSION && use_r1b_resp) {
|
||||
cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
|
||||
cmd.busy_timeout = busy_timeout_ms;
|
||||
} else {
|
||||
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
|
||||
use_r1b_resp = false;
|
||||
}
|
||||
if (cmd.opcode == MMC_STOP_TRANSMISSION)
|
||||
use_r1b_resp = mmc_prepare_busy_cmd(host, &cmd,
|
||||
busy_timeout_ms);
|
||||
|
||||
err = mmc_wait_for_cmd(host, &cmd, 0);
|
||||
if (err) {
|
||||
@ -848,7 +851,7 @@ static int mmc_send_hpi_cmd(struct mmc_card *card)
|
||||
return 0;
|
||||
|
||||
/* Let's poll to find out when the HPI request completes. */
|
||||
return mmc_poll_for_busy(card, busy_timeout_ms, MMC_BUSY_HPI);
|
||||
return mmc_poll_for_busy(card, busy_timeout_ms, false, MMC_BUSY_HPI);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -961,26 +964,6 @@ void mmc_run_bkops(struct mmc_card *card)
|
||||
}
|
||||
EXPORT_SYMBOL(mmc_run_bkops);
|
||||
|
||||
/*
|
||||
* Flush the cache to the non-volatile storage.
|
||||
*/
|
||||
int mmc_flush_cache(struct mmc_card *card)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (mmc_cache_enabled(card->host)) {
|
||||
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_FLUSH_CACHE, 1,
|
||||
MMC_CACHE_FLUSH_TIMEOUT_MS);
|
||||
if (err)
|
||||
pr_err("%s: cache flush error %d\n",
|
||||
mmc_hostname(card->host), err);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(mmc_flush_cache);
|
||||
|
||||
static int mmc_cmdq_switch(struct mmc_card *card, bool enable)
|
||||
{
|
||||
u8 val = enable ? EXT_CSD_CMDQ_MODE_ENABLED : 0;
|
||||
|
@ -14,10 +14,12 @@ enum mmc_busy_cmd {
|
||||
MMC_BUSY_CMD6,
|
||||
MMC_BUSY_ERASE,
|
||||
MMC_BUSY_HPI,
|
||||
MMC_BUSY_EXTR_SINGLE,
|
||||
};
|
||||
|
||||
struct mmc_host;
|
||||
struct mmc_card;
|
||||
struct mmc_command;
|
||||
|
||||
int mmc_select_card(struct mmc_card *card);
|
||||
int mmc_deselect_cards(struct mmc_host *host);
|
||||
@ -25,6 +27,8 @@ int mmc_set_dsr(struct mmc_host *host);
|
||||
int mmc_go_idle(struct mmc_host *host);
|
||||
int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
|
||||
int mmc_set_relative_addr(struct mmc_card *card);
|
||||
int mmc_send_adtc_data(struct mmc_card *card, struct mmc_host *host, u32 opcode,
|
||||
u32 args, void *buf, unsigned len);
|
||||
int mmc_send_csd(struct mmc_card *card, u32 *csd);
|
||||
int __mmc_send_status(struct mmc_card *card, u32 *status, unsigned int retries);
|
||||
int mmc_send_status(struct mmc_card *card, u32 *status);
|
||||
@ -35,15 +39,19 @@ int mmc_bus_test(struct mmc_card *card, u8 bus_width);
|
||||
int mmc_can_ext_csd(struct mmc_card *card);
|
||||
int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd);
|
||||
int mmc_switch_status(struct mmc_card *card, bool crc_err_fatal);
|
||||
bool mmc_prepare_busy_cmd(struct mmc_host *host, struct mmc_command *cmd,
|
||||
unsigned int timeout_ms);
|
||||
int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
|
||||
int (*busy_cb)(void *cb_data, bool *busy),
|
||||
void *cb_data);
|
||||
int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms,
|
||||
enum mmc_busy_cmd busy_cmd);
|
||||
bool retry_crc_err, enum mmc_busy_cmd busy_cmd);
|
||||
int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
|
||||
unsigned int timeout_ms, unsigned char timing,
|
||||
bool send_status, bool retry_crc_err, unsigned int retries);
|
||||
int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
|
||||
unsigned int timeout_ms);
|
||||
void mmc_run_bkops(struct mmc_card *card);
|
||||
int mmc_flush_cache(struct mmc_card *card);
|
||||
int mmc_cmdq_enable(struct mmc_card *card);
|
||||
int mmc_cmdq_disable(struct mmc_card *card);
|
||||
int mmc_sanitize(struct mmc_card *card, unsigned int timeout_ms);
|
||||
|
@ -66,6 +66,14 @@ static const unsigned int sd_au_size[] = {
|
||||
__res & __mask; \
|
||||
})
|
||||
|
||||
#define SD_POWEROFF_NOTIFY_TIMEOUT_MS 2000
|
||||
#define SD_WRITE_EXTR_SINGLE_TIMEOUT_MS 1000
|
||||
|
||||
struct sd_busy_data {
|
||||
struct mmc_card *card;
|
||||
u8 *reg_buf;
|
||||
};
|
||||
|
||||
/*
|
||||
* Given the decoded CSD structure, decode the raw CID to our CID structure.
|
||||
*/
|
||||
@ -222,7 +230,9 @@ static int mmc_decode_scr(struct mmc_card *card)
|
||||
else
|
||||
card->erased_byte = 0x0;
|
||||
|
||||
if (scr->sda_spec3)
|
||||
if (scr->sda_spec4)
|
||||
scr->cmds = UNSTUFF_BITS(resp, 32, 4);
|
||||
else if (scr->sda_spec3)
|
||||
scr->cmds = UNSTUFF_BITS(resp, 32, 2);
|
||||
|
||||
/* SD Spec says: any SD Card shall set at least bits 0 and 2 */
|
||||
@ -847,11 +857,13 @@ try_again:
|
||||
return err;
|
||||
|
||||
/*
|
||||
* In case CCS and S18A in the response is set, start Signal Voltage
|
||||
* Switch procedure. SPI mode doesn't support CMD11.
|
||||
* In case the S18A bit is set in the response, let's start the signal
|
||||
* voltage switch procedure. SPI mode doesn't support CMD11.
|
||||
* Note that, according to the spec, the S18A bit is not valid unless
|
||||
* the CCS bit is set as well. We deliberately deviate from the spec in
|
||||
* regards to this, which allows UHS-I to be supported for SDSC cards.
|
||||
*/
|
||||
if (!mmc_host_is_spi(host) && rocr &&
|
||||
((*rocr & 0x41000000) == 0x41000000)) {
|
||||
if (!mmc_host_is_spi(host) && rocr && (*rocr & 0x01000000)) {
|
||||
err = mmc_set_uhs_voltage(host, pocr);
|
||||
if (err == -EAGAIN) {
|
||||
retries--;
|
||||
@ -994,6 +1006,380 @@ 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;
|
||||
|
||||
/* Read the extension register for power management function. */
|
||||
err = 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);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* PM revision consists of 4 bits. */
|
||||
card->ext_power.rev = reg_buf[0] & 0xf;
|
||||
|
||||
/* Power Off Notification support at bit 4. */
|
||||
if (reg_buf[1] & BIT(4))
|
||||
card->ext_power.feature_support |= SD_EXT_POWER_OFF_NOTIFY;
|
||||
|
||||
/* Power Sustenance support at bit 5. */
|
||||
if (reg_buf[1] & BIT(5))
|
||||
card->ext_power.feature_support |= SD_EXT_POWER_SUSTENANCE;
|
||||
|
||||
/* Power Down Mode support at bit 6. */
|
||||
if (reg_buf[1] & BIT(6))
|
||||
card->ext_power.feature_support |= SD_EXT_POWER_DOWN_MODE;
|
||||
|
||||
card->ext_power.fno = fno;
|
||||
card->ext_power.page = page;
|
||||
card->ext_power.offset = offset;
|
||||
|
||||
out:
|
||||
kfree(reg_buf);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int sd_parse_ext_reg_perf(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;
|
||||
|
||||
err = 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);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* PERF revision. */
|
||||
card->ext_perf.rev = reg_buf[0];
|
||||
|
||||
/* FX_EVENT support at bit 0. */
|
||||
if (reg_buf[1] & BIT(0))
|
||||
card->ext_perf.feature_support |= SD_EXT_PERF_FX_EVENT;
|
||||
|
||||
/* Card initiated self-maintenance support at bit 0. */
|
||||
if (reg_buf[2] & BIT(0))
|
||||
card->ext_perf.feature_support |= SD_EXT_PERF_CARD_MAINT;
|
||||
|
||||
/* Host initiated self-maintenance support at bit 1. */
|
||||
if (reg_buf[2] & BIT(1))
|
||||
card->ext_perf.feature_support |= SD_EXT_PERF_HOST_MAINT;
|
||||
|
||||
/* Cache support at bit 0. */
|
||||
if (reg_buf[4] & BIT(0))
|
||||
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)
|
||||
card->ext_perf.feature_support |= SD_EXT_PERF_CMD_QUEUE;
|
||||
|
||||
card->ext_perf.fno = fno;
|
||||
card->ext_perf.page = page;
|
||||
card->ext_perf.offset = offset;
|
||||
|
||||
out:
|
||||
kfree(reg_buf);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int sd_parse_ext_reg(struct mmc_card *card, u8 *gen_info_buf,
|
||||
u16 *next_ext_addr)
|
||||
{
|
||||
u8 num_regs, fno, page;
|
||||
u16 sfc, offset, ext = *next_ext_addr;
|
||||
u32 reg_addr;
|
||||
|
||||
/*
|
||||
* Parse only one register set per extension, as that is sufficient to
|
||||
* support the standard functions. This means another 48 bytes in the
|
||||
* buffer must be available.
|
||||
*/
|
||||
if (ext + 48 > 512)
|
||||
return -EFAULT;
|
||||
|
||||
/* Standard Function Code */
|
||||
memcpy(&sfc, &gen_info_buf[ext], 2);
|
||||
|
||||
/* Address to the next extension. */
|
||||
memcpy(next_ext_addr, &gen_info_buf[ext + 40], 2);
|
||||
|
||||
/* Number of registers for this extension. */
|
||||
num_regs = gen_info_buf[ext + 42];
|
||||
|
||||
/* We support only one register per extension. */
|
||||
if (num_regs != 1)
|
||||
return 0;
|
||||
|
||||
/* Extension register address. */
|
||||
memcpy(®_addr, &gen_info_buf[ext + 44], 4);
|
||||
|
||||
/* 9 bits (0 to 8) contains the offset address. */
|
||||
offset = reg_addr & 0x1ff;
|
||||
|
||||
/* 8 bits (9 to 16) contains the page number. */
|
||||
page = reg_addr >> 9 & 0xff ;
|
||||
|
||||
/* 4 bits (18 to 21) contains the function number. */
|
||||
fno = reg_addr >> 18 & 0xf;
|
||||
|
||||
/* Standard Function Code for power management. */
|
||||
if (sfc == 0x1)
|
||||
return sd_parse_ext_reg_power(card, fno, page, offset);
|
||||
|
||||
/* Standard Function Code for performance enhancement. */
|
||||
if (sfc == 0x2)
|
||||
return sd_parse_ext_reg_perf(card, fno, page, offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_read_ext_regs(struct mmc_card *card)
|
||||
{
|
||||
int err, i;
|
||||
u8 num_ext, *gen_info_buf;
|
||||
u16 rev, len, next_ext_addr;
|
||||
|
||||
if (mmc_host_is_spi(card->host))
|
||||
return 0;
|
||||
|
||||
if (!(card->scr.cmds & SD_SCR_CMD48_SUPPORT))
|
||||
return 0;
|
||||
|
||||
gen_info_buf = kzalloc(512, GFP_KERNEL);
|
||||
if (!gen_info_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* 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);
|
||||
if (err) {
|
||||
pr_warn("%s: error %d reading general info of SD ext reg\n",
|
||||
mmc_hostname(card->host), err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* General info structure revision. */
|
||||
memcpy(&rev, &gen_info_buf[0], 2);
|
||||
|
||||
/* Length of general info in bytes. */
|
||||
memcpy(&len, &gen_info_buf[2], 2);
|
||||
|
||||
/* Number of extensions to be find. */
|
||||
num_ext = gen_info_buf[4];
|
||||
|
||||
/* We support revision 0, but limit it to 512 bytes for simplicity. */
|
||||
if (rev != 0 || len > 512) {
|
||||
pr_warn("%s: non-supported SD ext reg layout\n",
|
||||
mmc_hostname(card->host));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the extension registers. The first extension should start
|
||||
* immediately after the general info header (16 bytes).
|
||||
*/
|
||||
next_ext_addr = 16;
|
||||
for (i = 0; i < num_ext; i++) {
|
||||
err = sd_parse_ext_reg(card, gen_info_buf, &next_ext_addr);
|
||||
if (err) {
|
||||
pr_warn("%s: error %d parsing SD ext reg\n",
|
||||
mmc_hostname(card->host), err);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(gen_info_buf);
|
||||
return err;
|
||||
}
|
||||
|
||||
static bool sd_cache_enabled(struct mmc_host *host)
|
||||
{
|
||||
return host->card->ext_perf.feature_enabled & SD_EXT_PERF_CACHE;
|
||||
}
|
||||
|
||||
static int sd_flush_cache(struct mmc_host *host)
|
||||
{
|
||||
struct mmc_card *card = host->card;
|
||||
u8 *reg_buf, fno, page;
|
||||
u16 offset;
|
||||
int err;
|
||||
|
||||
if (!sd_cache_enabled(host))
|
||||
return 0;
|
||||
|
||||
reg_buf = kzalloc(512, GFP_KERNEL);
|
||||
if (!reg_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* Set Flush Cache at bit 0 in the performance enhancement register at
|
||||
* 261 bytes offset.
|
||||
*/
|
||||
fno = card->ext_perf.fno;
|
||||
page = card->ext_perf.page;
|
||||
offset = card->ext_perf.offset + 261;
|
||||
|
||||
err = 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);
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = mmc_poll_for_busy(card, SD_WRITE_EXTR_SINGLE_TIMEOUT_MS, false,
|
||||
MMC_BUSY_EXTR_SINGLE);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* 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);
|
||||
if (err) {
|
||||
pr_warn("%s: error %d reading Cache Flush bit\n",
|
||||
mmc_hostname(host), err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
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,
|
||||
card->ext_perf.offset + 260, BIT(0));
|
||||
if (err) {
|
||||
pr_warn("%s: error %d writing Cache Enable bit\n",
|
||||
mmc_hostname(card->host), err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = mmc_poll_for_busy(card, SD_WRITE_EXTR_SINGLE_TIMEOUT_MS, false,
|
||||
MMC_BUSY_EXTR_SINGLE);
|
||||
if (!err)
|
||||
card->ext_perf.feature_enabled |= SD_EXT_PERF_CACHE;
|
||||
|
||||
out:
|
||||
kfree(reg_buf);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle the detection and initialisation of a card.
|
||||
*
|
||||
@ -1142,6 +1528,20 @@ retry:
|
||||
}
|
||||
}
|
||||
|
||||
if (!oldcard) {
|
||||
/* Read/parse the extension registers. */
|
||||
err = sd_read_ext_regs(card);
|
||||
if (err)
|
||||
goto free_card;
|
||||
}
|
||||
|
||||
/* Enable internal SD cache if supported. */
|
||||
if (card->ext_perf.feature_support & SD_EXT_PERF_CACHE) {
|
||||
err = sd_enable_cache(card);
|
||||
if (err)
|
||||
goto free_card;
|
||||
}
|
||||
|
||||
if (host->cqe_ops && !host->cqe_enabled) {
|
||||
err = host->cqe_ops->cqe_enable(host, card);
|
||||
if (!err) {
|
||||
@ -1213,21 +1613,84 @@ static void mmc_sd_detect(struct mmc_host *host)
|
||||
}
|
||||
}
|
||||
|
||||
static int sd_can_poweroff_notify(struct mmc_card *card)
|
||||
{
|
||||
return card->ext_power.feature_support & SD_EXT_POWER_OFF_NOTIFY;
|
||||
}
|
||||
|
||||
static int sd_busy_poweroff_notify_cb(void *cb_data, bool *busy)
|
||||
{
|
||||
struct sd_busy_data *data = cb_data;
|
||||
struct mmc_card *card = data->card;
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Read the status register for the power management function. It's at
|
||||
* 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,
|
||||
card->ext_power.offset + 1, 1, data->reg_buf);
|
||||
if (err) {
|
||||
pr_warn("%s: error %d reading status reg of PM func\n",
|
||||
mmc_hostname(card->host), err);
|
||||
return err;
|
||||
}
|
||||
|
||||
*busy = !(data->reg_buf[0] & BIT(0));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_poweroff_notify(struct mmc_card *card)
|
||||
{
|
||||
struct sd_busy_data cb_data;
|
||||
u8 *reg_buf;
|
||||
int err;
|
||||
|
||||
reg_buf = kzalloc(512, GFP_KERNEL);
|
||||
if (!reg_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* 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,
|
||||
card->ext_power.offset + 2, BIT(0));
|
||||
if (err) {
|
||||
pr_warn("%s: error %d writing Power Off Notify bit\n",
|
||||
mmc_hostname(card->host), err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
cb_data.card = card;
|
||||
cb_data.reg_buf = reg_buf;
|
||||
err = __mmc_poll_for_busy(card, SD_POWEROFF_NOTIFY_TIMEOUT_MS,
|
||||
&sd_busy_poweroff_notify_cb, &cb_data);
|
||||
|
||||
out:
|
||||
kfree(reg_buf);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int _mmc_sd_suspend(struct mmc_host *host)
|
||||
{
|
||||
struct mmc_card *card = host->card;
|
||||
int err = 0;
|
||||
|
||||
mmc_claim_host(host);
|
||||
|
||||
if (mmc_card_suspended(host->card))
|
||||
if (mmc_card_suspended(card))
|
||||
goto out;
|
||||
|
||||
if (!mmc_host_is_spi(host))
|
||||
if (sd_can_poweroff_notify(card))
|
||||
err = sd_poweroff_notify(card);
|
||||
else if (!mmc_host_is_spi(host))
|
||||
err = mmc_deselect_cards(host);
|
||||
|
||||
if (!err) {
|
||||
mmc_power_off(host);
|
||||
mmc_card_set_suspended(host->card);
|
||||
mmc_card_set_suspended(card);
|
||||
}
|
||||
|
||||
out:
|
||||
@ -1331,6 +1794,8 @@ static const struct mmc_bus_ops mmc_sd_ops = {
|
||||
.alive = mmc_sd_alive,
|
||||
.shutdown = mmc_sd_suspend,
|
||||
.hw_reset = mmc_sd_hw_reset,
|
||||
.cache_enabled = sd_cache_enabled,
|
||||
.flush_cache = sd_flush_cache,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "core.h"
|
||||
#include "sd_ops.h"
|
||||
#include "mmc_ops.h"
|
||||
|
||||
int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card)
|
||||
{
|
||||
@ -309,43 +310,18 @@ int mmc_app_send_scr(struct mmc_card *card)
|
||||
int mmc_sd_switch(struct mmc_card *card, int mode, int group,
|
||||
u8 value, u8 *resp)
|
||||
{
|
||||
struct mmc_request mrq = {};
|
||||
struct mmc_command cmd = {};
|
||||
struct mmc_data data = {};
|
||||
struct scatterlist sg;
|
||||
u32 cmd_args;
|
||||
|
||||
/* NOTE: caller guarantees resp is heap-allocated */
|
||||
|
||||
mode = !!mode;
|
||||
value &= 0xF;
|
||||
cmd_args = mode << 31 | 0x00FFFFFF;
|
||||
cmd_args &= ~(0xF << (group * 4));
|
||||
cmd_args |= value << (group * 4);
|
||||
|
||||
mrq.cmd = &cmd;
|
||||
mrq.data = &data;
|
||||
|
||||
cmd.opcode = SD_SWITCH;
|
||||
cmd.arg = mode << 31 | 0x00FFFFFF;
|
||||
cmd.arg &= ~(0xF << (group * 4));
|
||||
cmd.arg |= value << (group * 4);
|
||||
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
|
||||
|
||||
data.blksz = 64;
|
||||
data.blocks = 1;
|
||||
data.flags = MMC_DATA_READ;
|
||||
data.sg = &sg;
|
||||
data.sg_len = 1;
|
||||
|
||||
sg_init_one(&sg, resp, 64);
|
||||
|
||||
mmc_set_data_timeout(&data, card);
|
||||
|
||||
mmc_wait_for_req(card->host, &mrq);
|
||||
|
||||
if (cmd.error)
|
||||
return cmd.error;
|
||||
if (data.error)
|
||||
return data.error;
|
||||
|
||||
return 0;
|
||||
return mmc_send_adtc_data(card, card->host, SD_SWITCH, cmd_args, resp,
|
||||
64);
|
||||
}
|
||||
|
||||
int mmc_app_sd_status(struct mmc_card *card, void *ssr)
|
||||
|
@ -937,11 +937,9 @@ static void mmc_sdio_detect(struct mmc_host *host)
|
||||
|
||||
/* Make sure card is powered before detecting it */
|
||||
if (host->caps & MMC_CAP_POWER_OFF_CARD) {
|
||||
err = pm_runtime_get_sync(&host->card->dev);
|
||||
if (err < 0) {
|
||||
pm_runtime_put_noidle(&host->card->dev);
|
||||
err = pm_runtime_resume_and_get(&host->card->dev);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
mmc_claim_host(host);
|
||||
|
@ -412,7 +412,7 @@ config MMC_SDHCI_MILBEAUT
|
||||
|
||||
config MMC_SDHCI_IPROC
|
||||
tristate "SDHCI support for the BCM2835 & iProc SD/MMC Controller"
|
||||
depends on ARCH_BCM2835 || ARCH_BCM_IPROC || COMPILE_TEST
|
||||
depends on ARCH_BCM2835 || ARCH_BCM_IPROC || ARCH_BRCMSTB || COMPILE_TEST
|
||||
depends on MMC_SDHCI_PLTFM
|
||||
depends on OF || ACPI
|
||||
default ARCH_BCM_IPROC
|
||||
|
@ -45,17 +45,23 @@ static inline u8 *get_link_desc(struct cqhci_host *cq_host, u8 tag)
|
||||
return desc + cq_host->task_desc_len;
|
||||
}
|
||||
|
||||
static inline size_t get_trans_desc_offset(struct cqhci_host *cq_host, u8 tag)
|
||||
{
|
||||
return cq_host->trans_desc_len * cq_host->mmc->max_segs * tag;
|
||||
}
|
||||
|
||||
static inline dma_addr_t get_trans_desc_dma(struct cqhci_host *cq_host, u8 tag)
|
||||
{
|
||||
return cq_host->trans_desc_dma_base +
|
||||
(cq_host->mmc->max_segs * tag *
|
||||
cq_host->trans_desc_len);
|
||||
size_t offset = get_trans_desc_offset(cq_host, tag);
|
||||
|
||||
return cq_host->trans_desc_dma_base + offset;
|
||||
}
|
||||
|
||||
static inline u8 *get_trans_desc(struct cqhci_host *cq_host, u8 tag)
|
||||
{
|
||||
return cq_host->trans_desc_base +
|
||||
(cq_host->trans_desc_len * cq_host->mmc->max_segs * tag);
|
||||
size_t offset = get_trans_desc_offset(cq_host, tag);
|
||||
|
||||
return cq_host->trans_desc_base + offset;
|
||||
}
|
||||
|
||||
static void setup_trans_desc(struct cqhci_host *cq_host, u8 tag)
|
||||
@ -146,7 +152,7 @@ static void cqhci_dumpregs(struct cqhci_host *cq_host)
|
||||
}
|
||||
|
||||
/*
|
||||
* The allocated descriptor table for task, link & transfer descritors
|
||||
* The allocated descriptor table for task, link & transfer descriptors
|
||||
* looks like:
|
||||
* |----------|
|
||||
* |task desc | |->|----------|
|
||||
@ -194,8 +200,7 @@ static int cqhci_host_alloc_tdl(struct cqhci_host *cq_host)
|
||||
|
||||
cq_host->desc_size = cq_host->slot_sz * cq_host->num_slots;
|
||||
|
||||
cq_host->data_size = cq_host->trans_desc_len * cq_host->mmc->max_segs *
|
||||
cq_host->mmc->cqe_qdepth;
|
||||
cq_host->data_size = get_trans_desc_offset(cq_host, cq_host->mmc->cqe_qdepth);
|
||||
|
||||
pr_debug("%s: cqhci: desc_size: %zu data_sz: %zu slot-sz: %d\n",
|
||||
mmc_hostname(cq_host->mmc), cq_host->desc_size, cq_host->data_size,
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/mmc/mmc.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include "dw_mmc.h"
|
||||
#include "dw_mmc-pltfm.h"
|
||||
|
@ -674,7 +674,7 @@ static void jz4740_mmc_send_command(struct jz4740_mmc_host *host,
|
||||
cmdat |= JZ_MMC_CMDAT_WRITE;
|
||||
if (host->use_dma) {
|
||||
/*
|
||||
* The 4780's MMC controller has integrated DMA ability
|
||||
* The JZ4780's MMC controller has integrated DMA ability
|
||||
* in addition to being able to use the external DMA
|
||||
* controller. It moves DMA control bits to a separate
|
||||
* register. The DMA_SEL bit chooses the external
|
||||
@ -866,7 +866,7 @@ static int jz4740_mmc_set_clock_rate(struct jz4740_mmc_host *host, int rate)
|
||||
writew(div, host->base + JZ_REG_MMC_CLKRT);
|
||||
|
||||
if (real_rate > 25000000) {
|
||||
if (host->version >= JZ_MMC_X1000) {
|
||||
if (host->version >= JZ_MMC_JZ4780) {
|
||||
writel(JZ_MMC_LPM_DRV_RISING_QTR_PHASE_DLY |
|
||||
JZ_MMC_LPM_SMP_RISING_QTR_OR_HALF_PHASE_DLY |
|
||||
JZ_MMC_LPM_LOW_POWER_MODE_EN,
|
||||
@ -959,6 +959,7 @@ static const struct of_device_id jz4740_mmc_of_match[] = {
|
||||
{ .compatible = "ingenic,jz4740-mmc", .data = (void *) JZ_MMC_JZ4740 },
|
||||
{ .compatible = "ingenic,jz4725b-mmc", .data = (void *)JZ_MMC_JZ4725B },
|
||||
{ .compatible = "ingenic,jz4760-mmc", .data = (void *) JZ_MMC_JZ4760 },
|
||||
{ .compatible = "ingenic,jz4775-mmc", .data = (void *) JZ_MMC_JZ4780 },
|
||||
{ .compatible = "ingenic,jz4780-mmc", .data = (void *) JZ_MMC_JZ4780 },
|
||||
{ .compatible = "ingenic,x1000-mmc", .data = (void *) JZ_MMC_X1000 },
|
||||
{},
|
||||
@ -1013,7 +1014,6 @@ static int jz4740_mmc_probe(struct platform_device* pdev)
|
||||
host->base = devm_ioremap_resource(&pdev->dev, host->mem_res);
|
||||
if (IS_ERR(host->base)) {
|
||||
ret = PTR_ERR(host->base);
|
||||
dev_err(&pdev->dev, "Failed to ioremap base memory\n");
|
||||
goto err_free_host;
|
||||
}
|
||||
|
||||
|
@ -504,7 +504,7 @@ mmc_spi_command_send(struct mmc_spi_host *host,
|
||||
/* else: R1 (most commands) */
|
||||
}
|
||||
|
||||
dev_dbg(&host->spi->dev, " mmc_spi: CMD%d, resp %s\n",
|
||||
dev_dbg(&host->spi->dev, " CMD%d, resp %s\n",
|
||||
cmd->opcode, maptype(cmd));
|
||||
|
||||
/* send command, leaving chipselect active */
|
||||
@ -928,8 +928,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
|
||||
while (length) {
|
||||
t->len = min(length, blk_size);
|
||||
|
||||
dev_dbg(&host->spi->dev,
|
||||
" mmc_spi: %s block, %d bytes\n",
|
||||
dev_dbg(&host->spi->dev, " %s block, %d bytes\n",
|
||||
(direction == DMA_TO_DEVICE) ? "write" : "read",
|
||||
t->len);
|
||||
|
||||
@ -974,7 +973,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd,
|
||||
int tmp;
|
||||
const unsigned statlen = sizeof(scratch->status);
|
||||
|
||||
dev_dbg(&spi->dev, " mmc_spi: STOP_TRAN\n");
|
||||
dev_dbg(&spi->dev, " STOP_TRAN\n");
|
||||
|
||||
/* Tweak the per-block message we set up earlier by morphing
|
||||
* it to hold single buffer with the token followed by some
|
||||
@ -1175,7 +1174,7 @@ static void mmc_spi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
||||
|
||||
canpower = host->pdata && host->pdata->setpower;
|
||||
|
||||
dev_dbg(&host->spi->dev, "mmc_spi: power %s (%d)%s\n",
|
||||
dev_dbg(&host->spi->dev, "power %s (%d)%s\n",
|
||||
mmc_powerstring(ios->power_mode),
|
||||
ios->vdd,
|
||||
canpower ? ", can switch" : "");
|
||||
@ -1248,8 +1247,7 @@ static void mmc_spi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
||||
|
||||
host->spi->max_speed_hz = ios->clock;
|
||||
status = spi_setup(host->spi);
|
||||
dev_dbg(&host->spi->dev,
|
||||
"mmc_spi: clock to %d Hz, %d\n",
|
||||
dev_dbg(&host->spi->dev, " clock to %d Hz, %d\n",
|
||||
host->spi->max_speed_hz, status);
|
||||
}
|
||||
}
|
||||
|
@ -724,10 +724,8 @@ static inline void msdc_dma_setup(struct msdc_host *host, struct msdc_dma *dma,
|
||||
writel(lower_32_bits(dma->gpd_addr), host->base + MSDC_DMA_SA);
|
||||
}
|
||||
|
||||
static void msdc_prepare_data(struct msdc_host *host, struct mmc_request *mrq)
|
||||
static void msdc_prepare_data(struct msdc_host *host, struct mmc_data *data)
|
||||
{
|
||||
struct mmc_data *data = mrq->data;
|
||||
|
||||
if (!(data->host_cookie & MSDC_PREPARE_FLAG)) {
|
||||
data->host_cookie |= MSDC_PREPARE_FLAG;
|
||||
data->sg_count = dma_map_sg(host->dev, data->sg, data->sg_len,
|
||||
@ -735,10 +733,8 @@ static void msdc_prepare_data(struct msdc_host *host, struct mmc_request *mrq)
|
||||
}
|
||||
}
|
||||
|
||||
static void msdc_unprepare_data(struct msdc_host *host, struct mmc_request *mrq)
|
||||
static void msdc_unprepare_data(struct msdc_host *host, struct mmc_data *data)
|
||||
{
|
||||
struct mmc_data *data = mrq->data;
|
||||
|
||||
if (data->host_cookie & MSDC_ASYNC_FLAG)
|
||||
return;
|
||||
|
||||
@ -1140,7 +1136,7 @@ static void msdc_request_done(struct msdc_host *host, struct mmc_request *mrq)
|
||||
|
||||
msdc_track_cmd_data(host, mrq->cmd, mrq->data);
|
||||
if (mrq->data)
|
||||
msdc_unprepare_data(host, mrq);
|
||||
msdc_unprepare_data(host, mrq->data);
|
||||
if (host->error)
|
||||
msdc_reset_hw(host);
|
||||
mmc_request_done(mmc_from_priv(host), mrq);
|
||||
@ -1311,7 +1307,7 @@ static void msdc_ops_request(struct mmc_host *mmc, struct mmc_request *mrq)
|
||||
host->mrq = mrq;
|
||||
|
||||
if (mrq->data)
|
||||
msdc_prepare_data(host, mrq);
|
||||
msdc_prepare_data(host, mrq->data);
|
||||
|
||||
/* if SBC is required, we have HW option and SW option.
|
||||
* if HW option is enabled, and SBC does not have "special" flags,
|
||||
@ -1332,7 +1328,7 @@ static void msdc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq)
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
msdc_prepare_data(host, mrq);
|
||||
msdc_prepare_data(host, data);
|
||||
data->host_cookie |= MSDC_ASYNC_FLAG;
|
||||
}
|
||||
|
||||
@ -1340,19 +1336,18 @@ static void msdc_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
|
||||
int err)
|
||||
{
|
||||
struct msdc_host *host = mmc_priv(mmc);
|
||||
struct mmc_data *data;
|
||||
struct mmc_data *data = mrq->data;
|
||||
|
||||
data = mrq->data;
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
if (data->host_cookie) {
|
||||
data->host_cookie &= ~MSDC_ASYNC_FLAG;
|
||||
msdc_unprepare_data(host, mrq);
|
||||
msdc_unprepare_data(host, data);
|
||||
}
|
||||
}
|
||||
|
||||
static void msdc_data_xfer_next(struct msdc_host *host,
|
||||
struct mmc_request *mrq, struct mmc_data *data)
|
||||
static void msdc_data_xfer_next(struct msdc_host *host, struct mmc_request *mrq)
|
||||
{
|
||||
if (mmc_op_multi(mrq->cmd->opcode) && mrq->stop && !mrq->stop->error &&
|
||||
!mrq->sbc)
|
||||
@ -1411,7 +1406,7 @@ static bool msdc_data_xfer_done(struct msdc_host *host, u32 events,
|
||||
(int)data->error, data->bytes_xfered);
|
||||
}
|
||||
|
||||
msdc_data_xfer_next(host, mrq, data);
|
||||
msdc_data_xfer_next(host, mrq);
|
||||
done = true;
|
||||
}
|
||||
return done;
|
||||
|
@ -22,8 +22,8 @@
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
struct of_mmc_spi {
|
||||
int detect_irq;
|
||||
struct mmc_spi_platform_data pdata;
|
||||
int detect_irq;
|
||||
};
|
||||
|
||||
static struct of_mmc_spi *to_of_mmc_spi(struct device *dev)
|
||||
|
@ -704,7 +704,7 @@ static int renesas_sdhi_execute_tuning(struct mmc_host *mmc, u32 opcode)
|
||||
set_bit(i, priv->smpcmp);
|
||||
|
||||
if (cmd_error)
|
||||
mmc_abort_tuning(mmc, opcode);
|
||||
mmc_send_abort_tuning(mmc, opcode);
|
||||
}
|
||||
|
||||
ret = renesas_sdhi_select_tuning(host);
|
||||
|
@ -1578,17 +1578,12 @@ static int s3cmci_probe(struct platform_device *pdev)
|
||||
goto probe_iounmap;
|
||||
}
|
||||
|
||||
if (request_irq(host->irq, s3cmci_irq, 0, DRIVER_NAME, host)) {
|
||||
if (request_irq(host->irq, s3cmci_irq, IRQF_NO_AUTOEN, DRIVER_NAME, host)) {
|
||||
dev_err(&pdev->dev, "failed to request mci interrupt.\n");
|
||||
ret = -ENOENT;
|
||||
goto probe_iounmap;
|
||||
}
|
||||
|
||||
/* We get spurious interrupts even when we have set the IMSK
|
||||
* register to ignore everything, so use disable_irq() to make
|
||||
* ensure we don't lock the system with un-serviceable requests. */
|
||||
|
||||
disable_irq(host->irq);
|
||||
host->irq_state = false;
|
||||
|
||||
/* Depending on the dma state, get a DMA channel to use. */
|
||||
|
@ -822,6 +822,17 @@ static const struct dmi_system_id sdhci_acpi_quirks[] = {
|
||||
},
|
||||
.driver_data = (void *)DMI_QUIRK_SD_NO_WRITE_PROTECT,
|
||||
},
|
||||
{
|
||||
/*
|
||||
* The Toshiba WT8-B's microSD slot always reports the card being
|
||||
* write-protected.
|
||||
*/
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "TOSHIBA ENCORE 2 WT8-B"),
|
||||
},
|
||||
.driver_data = (void *)DMI_QUIRK_SD_NO_WRITE_PROTECT,
|
||||
},
|
||||
{} /* Terminating entry */
|
||||
};
|
||||
|
||||
|
@ -324,11 +324,6 @@ static inline int is_imx53_esdhc(struct pltfm_imx_data *data)
|
||||
return data->socdata == &esdhc_imx53_data;
|
||||
}
|
||||
|
||||
static inline int is_imx6q_usdhc(struct pltfm_imx_data *data)
|
||||
{
|
||||
return data->socdata == &usdhc_imx6q_data;
|
||||
}
|
||||
|
||||
static inline int esdhc_is_usdhc(struct pltfm_imx_data *data)
|
||||
{
|
||||
return !!(data->socdata->flags & ESDHC_FLAG_USDHC);
|
||||
@ -427,9 +422,6 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
|
||||
| FIELD_PREP(SDHCI_RETUNING_MODE_MASK,
|
||||
SDHCI_TUNING_MODE_3);
|
||||
|
||||
if (imx_data->socdata->flags & ESDHC_FLAG_HS400)
|
||||
val |= SDHCI_SUPPORT_HS400;
|
||||
|
||||
/*
|
||||
* Do not advertise faster UHS modes if there are no
|
||||
* pinctrl states for 100MHz/200MHz.
|
||||
@ -1591,7 +1583,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
|
||||
host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
|
||||
|
||||
if (imx_data->socdata->flags & ESDHC_FLAG_HS400)
|
||||
host->quirks2 |= SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400;
|
||||
host->mmc->caps2 |= MMC_CAP2_HS400;
|
||||
|
||||
if (imx_data->socdata->flags & ESDHC_FLAG_BROKEN_AUTO_CMD23)
|
||||
host->quirks2 |= SDHCI_QUIRK2_ACMD23_BROKEN;
|
||||
@ -1628,6 +1620,14 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
|
||||
if (err)
|
||||
goto disable_ahb_clk;
|
||||
|
||||
/*
|
||||
* Setup the wakeup capability here, let user to decide
|
||||
* whether need to enable this wakeup through sysfs interface.
|
||||
*/
|
||||
if ((host->mmc->pm_caps & MMC_PM_KEEP_POWER) &&
|
||||
(host->mmc->pm_caps & MMC_PM_WAKE_SDIO_IRQ))
|
||||
device_set_wakeup_capable(&pdev->dev, true);
|
||||
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
|
||||
pm_runtime_use_autosuspend(&pdev->dev);
|
||||
|
@ -286,11 +286,35 @@ static const struct sdhci_iproc_data bcm2711_data = {
|
||||
.mmc_caps = MMC_CAP_3_3V_DDR,
|
||||
};
|
||||
|
||||
static const struct sdhci_pltfm_data sdhci_bcm7211a0_pltfm_data = {
|
||||
.quirks = SDHCI_QUIRK_MISSING_CAPS |
|
||||
SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
|
||||
SDHCI_QUIRK_BROKEN_DMA |
|
||||
SDHCI_QUIRK_BROKEN_ADMA,
|
||||
.ops = &sdhci_iproc_ops,
|
||||
};
|
||||
|
||||
#define BCM7211A0_BASE_CLK_MHZ 100
|
||||
static const struct sdhci_iproc_data bcm7211a0_data = {
|
||||
.pdata = &sdhci_bcm7211a0_pltfm_data,
|
||||
.caps = ((BCM7211A0_BASE_CLK_MHZ / 2) << SDHCI_TIMEOUT_CLK_SHIFT) |
|
||||
(BCM7211A0_BASE_CLK_MHZ << SDHCI_CLOCK_BASE_SHIFT) |
|
||||
((0x2 << SDHCI_MAX_BLOCK_SHIFT)
|
||||
& SDHCI_MAX_BLOCK_MASK) |
|
||||
SDHCI_CAN_VDD_330 |
|
||||
SDHCI_CAN_VDD_180 |
|
||||
SDHCI_CAN_DO_SUSPEND |
|
||||
SDHCI_CAN_DO_HISPD,
|
||||
.caps1 = SDHCI_DRIVER_TYPE_C |
|
||||
SDHCI_DRIVER_TYPE_D,
|
||||
};
|
||||
|
||||
static const struct of_device_id sdhci_iproc_of_match[] = {
|
||||
{ .compatible = "brcm,bcm2835-sdhci", .data = &bcm2835_data },
|
||||
{ .compatible = "brcm,bcm2711-emmc2", .data = &bcm2711_data },
|
||||
{ .compatible = "brcm,sdhci-iproc-cygnus", .data = &iproc_cygnus_data},
|
||||
{ .compatible = "brcm,sdhci-iproc", .data = &iproc_data },
|
||||
{ .compatible = "brcm,bcm7211a0-sdhci", .data = &bcm7211a0_data },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, sdhci_iproc_of_match);
|
||||
@ -384,6 +408,11 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sdhci_iproc_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
sdhci_pltfm_suspend(&pdev->dev);
|
||||
}
|
||||
|
||||
static struct platform_driver sdhci_iproc_driver = {
|
||||
.driver = {
|
||||
.name = "sdhci-iproc",
|
||||
@ -394,6 +423,7 @@ static struct platform_driver sdhci_iproc_driver = {
|
||||
},
|
||||
.probe = sdhci_iproc_probe,
|
||||
.remove = sdhci_pltfm_unregister,
|
||||
.shutdown = sdhci_iproc_shutdown,
|
||||
};
|
||||
module_platform_driver(sdhci_iproc_driver);
|
||||
|
||||
|
@ -31,6 +31,11 @@
|
||||
#define ASPEED_SDC_S0_PHASE_OUT_EN GENMASK(1, 0)
|
||||
#define ASPEED_SDC_PHASE_MAX 31
|
||||
|
||||
/* SDIO{10,20} */
|
||||
#define ASPEED_SDC_CAP1_1_8V (0 * 32 + 26)
|
||||
/* SDIO{14,24} */
|
||||
#define ASPEED_SDC_CAP2_SDR104 (1 * 32 + 1)
|
||||
|
||||
struct aspeed_sdc {
|
||||
struct clk *clk;
|
||||
struct resource *res;
|
||||
@ -72,6 +77,37 @@ struct aspeed_sdhci {
|
||||
const struct aspeed_sdhci_phase_desc *phase_desc;
|
||||
};
|
||||
|
||||
/*
|
||||
* The function sets the mirror register for updating
|
||||
* capbilities of the current slot.
|
||||
*
|
||||
* slot | capability | caps_reg | mirror_reg
|
||||
* -----|-------------|----------|------------
|
||||
* 0 | CAP1_1_8V | SDIO140 | SDIO10
|
||||
* 0 | CAP2_SDR104 | SDIO144 | SDIO14
|
||||
* 1 | CAP1_1_8V | SDIO240 | SDIO20
|
||||
* 1 | CAP2_SDR104 | SDIO244 | SDIO24
|
||||
*/
|
||||
static void aspeed_sdc_set_slot_capability(struct sdhci_host *host, struct aspeed_sdc *sdc,
|
||||
int capability, bool enable, u8 slot)
|
||||
{
|
||||
u32 mirror_reg_offset;
|
||||
u32 cap_val;
|
||||
u8 cap_reg;
|
||||
|
||||
if (slot > 1)
|
||||
return;
|
||||
|
||||
cap_reg = capability / 32;
|
||||
cap_val = sdhci_readl(host, 0x40 + (cap_reg * 4));
|
||||
if (enable)
|
||||
cap_val |= BIT(capability % 32);
|
||||
else
|
||||
cap_val &= ~BIT(capability % 32);
|
||||
mirror_reg_offset = ((slot + 1) * 0x10) + (cap_reg * 4);
|
||||
writel(cap_val, sdc->regs + mirror_reg_offset);
|
||||
}
|
||||
|
||||
static void aspeed_sdc_configure_8bit_mode(struct aspeed_sdc *sdc,
|
||||
struct aspeed_sdhci *sdhci,
|
||||
bool bus8)
|
||||
@ -150,7 +186,7 @@ static int aspeed_sdhci_phase_to_tap(struct device *dev, unsigned long rate_hz,
|
||||
|
||||
tap = div_u64(phase_period_ps, prop_delay_ps);
|
||||
if (tap > ASPEED_SDHCI_NR_TAPS) {
|
||||
dev_warn(dev,
|
||||
dev_dbg(dev,
|
||||
"Requested out of range phase tap %d for %d degrees of phase compensation at %luHz, clamping to tap %d\n",
|
||||
tap, phase_deg, rate_hz, ASPEED_SDHCI_NR_TAPS);
|
||||
tap = ASPEED_SDHCI_NR_TAPS;
|
||||
@ -328,6 +364,7 @@ static inline int aspeed_sdhci_calculate_slot(struct aspeed_sdhci *dev,
|
||||
static int aspeed_sdhci_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct aspeed_sdhci_pdata *aspeed_pdata;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct sdhci_pltfm_host *pltfm_host;
|
||||
struct aspeed_sdhci *dev;
|
||||
struct sdhci_host *host;
|
||||
@ -372,6 +409,17 @@ static int aspeed_sdhci_probe(struct platform_device *pdev)
|
||||
|
||||
sdhci_get_of_property(pdev);
|
||||
|
||||
if (of_property_read_bool(np, "mmc-hs200-1_8v") ||
|
||||
of_property_read_bool(np, "sd-uhs-sdr104")) {
|
||||
aspeed_sdc_set_slot_capability(host, dev->parent, ASPEED_SDC_CAP1_1_8V,
|
||||
true, slot);
|
||||
}
|
||||
|
||||
if (of_property_read_bool(np, "sd-uhs-sdr104")) {
|
||||
aspeed_sdc_set_slot_capability(host, dev->parent, ASPEED_SDC_CAP2_SDR104,
|
||||
true, slot);
|
||||
}
|
||||
|
||||
pltfm_host->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(pltfm_host->clk))
|
||||
return PTR_ERR(pltfm_host->clk);
|
||||
|
@ -1173,10 +1173,9 @@ static int sdhci_omap_probe(struct platform_device *pdev)
|
||||
* as part of pm_runtime_get_sync.
|
||||
*/
|
||||
pm_runtime_enable(dev);
|
||||
ret = pm_runtime_get_sync(dev);
|
||||
if (ret < 0) {
|
||||
ret = pm_runtime_resume_and_get(dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "pm_runtime_get_sync failed\n");
|
||||
pm_runtime_put_noidle(dev);
|
||||
goto err_rpm_disable;
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,7 @@
|
||||
|
||||
#define PCIE_GLI_9763E_CFG2 0x8A4
|
||||
#define GLI_9763E_CFG2_L1DLY GENMASK(28, 19)
|
||||
#define GLI_9763E_CFG2_L1DLY_MID 0x50
|
||||
#define GLI_9763E_CFG2_L1DLY_MID 0x54
|
||||
|
||||
#define PCIE_GLI_9763E_MMC_CTRL 0x960
|
||||
#define GLI_9763E_HS400_SLOW BIT(3)
|
||||
@ -847,7 +847,7 @@ static void gli_set_gl9763e(struct sdhci_pci_slot *slot)
|
||||
|
||||
pci_read_config_dword(pdev, PCIE_GLI_9763E_CFG2, &value);
|
||||
value &= ~GLI_9763E_CFG2_L1DLY;
|
||||
/* set ASPM L1 entry delay to 20us */
|
||||
/* set ASPM L1 entry delay to 21us */
|
||||
value |= FIELD_PREP(GLI_9763E_CFG2_L1DLY, GLI_9763E_CFG2_L1DLY_MID);
|
||||
pci_write_config_dword(pdev, PCIE_GLI_9763E_CFG2, value);
|
||||
|
||||
|
@ -393,6 +393,7 @@ static void sdhci_sprd_request_done(struct sdhci_host *host,
|
||||
static struct sdhci_ops sdhci_sprd_ops = {
|
||||
.read_l = sdhci_sprd_readl,
|
||||
.write_l = sdhci_sprd_writel,
|
||||
.write_w = sdhci_sprd_writew,
|
||||
.write_b = sdhci_sprd_writeb,
|
||||
.set_clock = sdhci_sprd_set_clock,
|
||||
.get_max_clock = sdhci_sprd_get_max_clock,
|
||||
|
@ -2680,7 +2680,7 @@ void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode)
|
||||
|
||||
sdhci_end_tuning(host);
|
||||
|
||||
mmc_abort_tuning(host->mmc, opcode);
|
||||
mmc_send_abort_tuning(host->mmc, opcode);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sdhci_abort_tuning);
|
||||
|
||||
|
@ -201,8 +201,10 @@
|
||||
|
||||
#define SDHCI_CAPABILITIES 0x40
|
||||
#define SDHCI_TIMEOUT_CLK_MASK GENMASK(5, 0)
|
||||
#define SDHCI_TIMEOUT_CLK_SHIFT 0
|
||||
#define SDHCI_TIMEOUT_CLK_UNIT 0x00000080
|
||||
#define SDHCI_CLOCK_BASE_MASK GENMASK(13, 8)
|
||||
#define SDHCI_CLOCK_BASE_SHIFT 8
|
||||
#define SDHCI_CLOCK_V3_BASE_MASK GENMASK(15, 8)
|
||||
#define SDHCI_MAX_BLOCK_MASK 0x00030000
|
||||
#define SDHCI_MAX_BLOCK_SHIFT 16
|
||||
|
@ -809,11 +809,9 @@ static int sdhci_am654_probe(struct platform_device *pdev)
|
||||
|
||||
/* Clocks are enabled using pm_runtime */
|
||||
pm_runtime_enable(dev);
|
||||
ret = pm_runtime_get_sync(dev);
|
||||
if (ret < 0) {
|
||||
pm_runtime_put_noidle(dev);
|
||||
ret = pm_runtime_resume_and_get(dev);
|
||||
if (ret)
|
||||
goto pm_runtime_disable;
|
||||
}
|
||||
|
||||
base = devm_platform_ioremap_resource(pdev, 1);
|
||||
if (IS_ERR(base)) {
|
||||
|
@ -1801,6 +1801,7 @@ static int usdhi6_probe(struct platform_device *pdev)
|
||||
|
||||
version = usdhi6_read(host, USDHI6_VERSION);
|
||||
if ((version & 0xfff) != 0xa0d) {
|
||||
ret = -EPERM;
|
||||
dev_err(dev, "Version not recognized %x\n", version);
|
||||
goto e_clk_off;
|
||||
}
|
||||
|
@ -857,6 +857,9 @@ static void via_sdc_data_isr(struct via_crdr_mmc_host *host, u16 intmask)
|
||||
{
|
||||
BUG_ON(intmask == 0);
|
||||
|
||||
if (!host->data)
|
||||
return;
|
||||
|
||||
if (intmask & VIA_CRDR_SDSTS_DT)
|
||||
host->data->error = -ETIMEDOUT;
|
||||
else if (intmask & (VIA_CRDR_SDSTS_RC | VIA_CRDR_SDSTS_WC))
|
||||
|
@ -2279,7 +2279,7 @@ static int vub300_probe(struct usb_interface *interface,
|
||||
if (retval < 0)
|
||||
goto error5;
|
||||
retval =
|
||||
usb_control_msg(vub300->udev, usb_rcvctrlpipe(vub300->udev, 0),
|
||||
usb_control_msg(vub300->udev, usb_sndctrlpipe(vub300->udev, 0),
|
||||
SET_ROM_WAIT_STATES,
|
||||
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
firmware_rom_wait_states, 0x0000, NULL, 0, HZ);
|
||||
|
@ -139,6 +139,8 @@ struct sd_scr {
|
||||
unsigned char cmds;
|
||||
#define SD_SCR_CMD20_SUPPORT (1<<0)
|
||||
#define SD_SCR_CMD23_SUPPORT (1<<1)
|
||||
#define SD_SCR_CMD48_SUPPORT (1<<2)
|
||||
#define SD_SCR_CMD58_SUPPORT (1<<3)
|
||||
};
|
||||
|
||||
struct sd_ssr {
|
||||
@ -189,6 +191,25 @@ struct sd_switch_caps {
|
||||
#define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800)
|
||||
};
|
||||
|
||||
struct sd_ext_reg {
|
||||
u8 fno;
|
||||
u8 page;
|
||||
u16 offset;
|
||||
u8 rev;
|
||||
u8 feature_enabled;
|
||||
u8 feature_support;
|
||||
/* Power Management Function. */
|
||||
#define SD_EXT_POWER_OFF_NOTIFY (1<<0)
|
||||
#define SD_EXT_POWER_SUSTENANCE (1<<1)
|
||||
#define SD_EXT_POWER_DOWN_MODE (1<<2)
|
||||
/* Performance Enhancement Function. */
|
||||
#define SD_EXT_PERF_FX_EVENT (1<<0)
|
||||
#define SD_EXT_PERF_CARD_MAINT (1<<1)
|
||||
#define SD_EXT_PERF_HOST_MAINT (1<<2)
|
||||
#define SD_EXT_PERF_CACHE (1<<3)
|
||||
#define SD_EXT_PERF_CMD_QUEUE (1<<4)
|
||||
};
|
||||
|
||||
struct sdio_cccr {
|
||||
unsigned int sdio_vsn;
|
||||
unsigned int sd_vsn;
|
||||
@ -290,6 +311,8 @@ struct mmc_card {
|
||||
struct sd_scr scr; /* extra SD information */
|
||||
struct sd_ssr ssr; /* yet more SD information */
|
||||
struct sd_switch_caps sw_caps; /* switch (CMD6) caps */
|
||||
struct sd_ext_reg ext_power; /* SD extension reg for PM */
|
||||
struct sd_ext_reg ext_perf; /* SD extension reg for PERF */
|
||||
|
||||
unsigned int sdio_funcs; /* number of SDIO functions */
|
||||
atomic_t sdio_funcs_probed; /* number of probed SDIO funcs */
|
||||
|
@ -632,6 +632,6 @@ static inline enum dma_data_direction mmc_get_dma_dir(struct mmc_data *data)
|
||||
}
|
||||
|
||||
int mmc_send_tuning(struct mmc_host *host, u32 opcode, int *cmd_error);
|
||||
int mmc_abort_tuning(struct mmc_host *host, u32 opcode);
|
||||
int mmc_send_abort_tuning(struct mmc_host *host, u32 opcode);
|
||||
|
||||
#endif /* LINUX_MMC_HOST_H */
|
||||
|
@ -29,6 +29,10 @@
|
||||
#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */
|
||||
#define SD_APP_SEND_SCR 51 /* adtc R1 */
|
||||
|
||||
/* class 11 */
|
||||
#define SD_READ_EXTR_SINGLE 48 /* adtc [31:0] R1 */
|
||||
#define SD_WRITE_EXTR_SINGLE 49 /* adtc [31:0] R1 */
|
||||
|
||||
/* OCR bit definitions */
|
||||
#define SD_OCR_S18R (1 << 24) /* 1.8V switching request */
|
||||
#define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */
|
||||
|
Loading…
Reference in New Issue
Block a user