You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'mmc-v4.2' of git://git.linaro.org/people/ulf.hansson/mmc
Pull MMC updates from Ulf Hansson: "Here are the changes for MMC for v4.2. MMC core: - Fix an error path in the mmc block layer - Fix PM domain attachment for the SDIO bus - Add support for driver strength selection - Increase a delay to let voltage stabilize - Add support for disabling write-protect detection - Add facility to support re-tuning - Re-tune and retry in the recovery path - Add reset option for SDIO - Consolidations and clean-ups MMC host: - Add Mediatek MMC driver - Constify platform_device_id for a couple of hosts - Fix modalias to make module auto-loading work for a couple of hosts - sdhci: Add support for sdhci-arasan4.9a - sdhci: Fix low memory corruption - sdhci: Restore behavior while creating OCR mask - sdhci: Add a callback to select drive strength - sdhci: Fix driver type B and D handling - sdhci: Add support for drive strength selection for SPT - sdhci: Enable HS400 for some Intel host controllers - sdhci: Convert to use the new re-tuning facility - sdhci: Various minor fixes and clean-ups - dw_mmc: Add support for hi6220 - dw_mmc: Use core to handle absent write protect line - dw_mmc: Add support to switch voltage - tmio: Some fixes and modernizations - sh_mmcif: Improve clock rate calculation" * tag 'mmc-v4.2' of git://git.linaro.org/people/ulf.hansson/mmc: (98 commits) mmc: queue: prevent soft lockups on PREEMPT=n mmc: mediatek: Add PM support for MMC driver mmc: mediatek: Add Mediatek MMC driver mmc: dt-bindings: add Mediatek MMC bindings mmc: card: Fixup request missing in mmc_blk_issue_rw_rq mmc: sdhci: fix low memory corruption mmc: sdhci-pci: Change AMD SDHCI quirk application scope i2c-piix4: Use Macro for AMD CZ SMBus device ID pci_ids: Add AMD KERNCZ device ID support mmc: queue: use swap() in mmc_queue_thread() mmc: dw_mmc: insmod followed by rmmod will hung for eMMC mmc: sdhci: Restore behavior while creating OCR mask mmc: sdhci-pxav3: fix device wakeup initialization mmc: core: Attach PM domain prior probing of SDIO func driver mmc: core: Remove redundant ->power_restore() callback for SD mmc: core: Remove redundant ->power_restore() callback for MMC mmc: sdhci-bcm2835: Actually enable the clock mmc: sdhci-bcm2835: Clean up platform allocations if sdhci init fails. mmc: sdhci-of-esdhc: enable interrupt mode to detect card mmc: sdhci-esdhc-imx: add quirk SDHCI_QUIRK2_BROKEN_HS200 for imx6qdl ...
This commit is contained in:
@@ -8,7 +8,8 @@ Device Tree Bindings for the Arasan SDHCI Controller
|
||||
[3] Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
|
||||
|
||||
Required Properties:
|
||||
- compatible: Compatibility string. Must be 'arasan,sdhci-8.9a'
|
||||
- compatible: Compatibility string. Must be 'arasan,sdhci-8.9a' or
|
||||
'arasan,sdhci-4.9a'
|
||||
- reg: From mmc bindings: Register location and length.
|
||||
- clocks: From clock bindings: Handles to clock inputs.
|
||||
- clock-names: From clock bindings: Tuple including "clk_xin" and "clk_ahb"
|
||||
|
||||
@@ -7,7 +7,14 @@ This file documents differences between the core properties described
|
||||
by mmc.txt and the properties used by the sdhci-esdhc-imx driver.
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be "fsl,<chip>-esdhc"
|
||||
- compatible : Should be "fsl,<chip>-esdhc", the supported chips include
|
||||
"fsl,imx25-esdhc"
|
||||
"fsl,imx35-esdhc"
|
||||
"fsl,imx51-esdhc"
|
||||
"fsl,imx53-esdhc"
|
||||
"fsl,imx6q-usdhc"
|
||||
"fsl,imx6sl-usdhc"
|
||||
"fsl,imx6sx-usdhc"
|
||||
|
||||
Optional properties:
|
||||
- fsl,cd-controller : Indicate to use controller internal card detection
|
||||
|
||||
@@ -13,6 +13,10 @@ Required Properties:
|
||||
|
||||
* compatible: should be one of the following.
|
||||
- "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extensions.
|
||||
- "hisilicon,hi6220-dw-mshc": for controllers with hi6220 specific extensions.
|
||||
|
||||
Optional Properties:
|
||||
- hisilicon,peripheral-syscon: phandle of syscon used to control peripheral.
|
||||
|
||||
Example:
|
||||
|
||||
@@ -42,3 +46,27 @@ Example:
|
||||
cap-mmc-highspeed;
|
||||
cap-sd-highspeed;
|
||||
};
|
||||
|
||||
/* for Hi6220 */
|
||||
|
||||
dwmmc_1: dwmmc1@f723e000 {
|
||||
compatible = "hisilicon,hi6220-dw-mshc";
|
||||
num-slots = <0x1>;
|
||||
bus-width = <0x4>;
|
||||
disable-wp;
|
||||
cap-sd-highspeed;
|
||||
sd-uhs-sdr12;
|
||||
sd-uhs-sdr25;
|
||||
card-detect-delay = <200>;
|
||||
hisilicon,peripheral-syscon = <&ao_ctrl>;
|
||||
reg = <0x0 0xf723e000 0x0 0x1000>;
|
||||
interrupts = <0x0 0x49 0x4>;
|
||||
clocks = <&clock_sys HI6220_MMC1_CIUCLK>, <&clock_sys HI6220_MMC1_CLK>;
|
||||
clock-names = "ciu", "biu";
|
||||
cd-gpios = <&gpio1 0 1>;
|
||||
pinctrl-names = "default", "idle";
|
||||
pinctrl-0 = <&sd_pmx_func &sd_clk_cfg_func &sd_cfg_func>;
|
||||
pinctrl-1 = <&sd_pmx_idle &sd_clk_cfg_idle &sd_cfg_idle>;
|
||||
vqmmc-supply = <&ldo7>;
|
||||
vmmc-supply = <&ldo10>;
|
||||
};
|
||||
|
||||
@@ -21,5 +21,7 @@ Example:
|
||||
|
||||
sdhci0_pwrseq {
|
||||
compatible = "mmc-pwrseq-simple";
|
||||
reset-gpios = <&gpio1 12 0>;
|
||||
reset-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
|
||||
clocks = <&clk_32768_ck>;
|
||||
clock-names = "ext_clock";
|
||||
}
|
||||
|
||||
@@ -21,6 +21,11 @@ Optional properties:
|
||||
below for the case, when a GPIO is used for the CD line
|
||||
- wp-inverted: when present, polarity on the WP line is inverted. See the note
|
||||
below for the case, when a GPIO is used for the WP line
|
||||
- disable-wp: When set no physical WP line is present. This property should
|
||||
only be specified when the controller has a dedicated write-protect
|
||||
detection logic. If a GPIO is always used for the write-protect detection
|
||||
logic it is sufficient to not specify wp-gpios property in the absence of a WP
|
||||
line.
|
||||
- max-frequency: maximum operating clock frequency
|
||||
- no-1-8-v: when present, denotes that 1.8v card voltage is not supported on
|
||||
this system, even if the controller claims it is.
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
* MTK MMC controller
|
||||
|
||||
The MTK MSDC can act as a MMC controller
|
||||
to support MMC, SD, and SDIO types of memory cards.
|
||||
|
||||
This file documents differences between the core properties in mmc.txt
|
||||
and the properties used by the msdc driver.
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "mediatek,mt8173-mmc","mediatek,mt8135-mmc"
|
||||
- interrupts: Should contain MSDC interrupt number
|
||||
- clocks: MSDC source clock, HCLK
|
||||
- clock-names: "source", "hclk"
|
||||
- pinctrl-names: should be "default", "state_uhs"
|
||||
- pinctrl-0: should contain default/high speed pin ctrl
|
||||
- pinctrl-1: should contain uhs mode pin ctrl
|
||||
- vmmc-supply: power to the Core
|
||||
- vqmmc-supply: power to the IO
|
||||
|
||||
Examples:
|
||||
mmc0: mmc@11230000 {
|
||||
compatible = "mediatek,mt8173-mmc", "mediatek,mt8135-mmc";
|
||||
reg = <0 0x11230000 0 0x108>;
|
||||
interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_LOW>;
|
||||
vmmc-supply = <&mt6397_vemc_3v3_reg>;
|
||||
vqmmc-supply = <&mt6397_vio18_reg>;
|
||||
clocks = <&pericfg CLK_PERI_MSDC30_0>, <&topckgen CLK_TOP_MSDC50_0_H_SEL>;
|
||||
clock-names = "source", "hclk";
|
||||
pinctrl-names = "default", "state_uhs";
|
||||
pinctrl-0 = <&mmc0_pins_default>;
|
||||
pinctrl-1 = <&mmc0_pins_uhs>;
|
||||
};
|
||||
@@ -18,6 +18,8 @@ Required properties:
|
||||
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
|
||||
@@ -29,4 +31,5 @@ Example: R8A7790 (R-Car H2) MMCIF0
|
||||
clocks = <&mstp3_clks R8A7790_CLK_MMCIF0>;
|
||||
dmas = <&dmac0 0xd1>, <&dmac0 0xd2>;
|
||||
dma-names = "tx", "rx";
|
||||
max-frequency = <97500000>;
|
||||
};
|
||||
|
||||
+1
-1
@@ -10033,7 +10033,7 @@ F: include/linux/toshiba.h
|
||||
F: include/uapi/linux/toshiba.h
|
||||
|
||||
TMIO MMC DRIVER
|
||||
M: Ian Molton <ian.molton@codethink.co.uk>
|
||||
M: Ian Molton <ian@mnementh.co.uk>
|
||||
L: linux-mmc@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/mmc/host/tmio_mmc*
|
||||
|
||||
@@ -370,6 +370,7 @@
|
||||
|
||||
/include/ "qoriq-esdhc-0.dtsi"
|
||||
sdhc@114000 {
|
||||
compatible = "fsl,p2041-esdhc", "fsl,esdhc";
|
||||
fsl,iommu-parent = <&pamu1>;
|
||||
fsl,liodn-reg = <&guts 0x530>; /* eSDHCLIODNR */
|
||||
sdhci,auto-cmd12;
|
||||
|
||||
@@ -397,6 +397,7 @@
|
||||
|
||||
/include/ "qoriq-esdhc-0.dtsi"
|
||||
sdhc@114000 {
|
||||
compatible = "fsl,p3041-esdhc", "fsl,esdhc";
|
||||
fsl,iommu-parent = <&pamu1>;
|
||||
fsl,liodn-reg = <&guts 0x530>; /* eSDHCLIODNR */
|
||||
sdhci,auto-cmd12;
|
||||
|
||||
@@ -469,6 +469,7 @@
|
||||
|
||||
/include/ "qoriq-esdhc-0.dtsi"
|
||||
sdhc@114000 {
|
||||
compatible = "fsl,p4080-esdhc", "fsl,esdhc";
|
||||
fsl,iommu-parent = <&pamu1>;
|
||||
fsl,liodn-reg = <&guts 0x530>; /* eSDHCLIODNR */
|
||||
voltage-ranges = <3300 3300>;
|
||||
|
||||
@@ -384,6 +384,7 @@
|
||||
|
||||
/include/ "qoriq-esdhc-0.dtsi"
|
||||
sdhc@114000 {
|
||||
compatible = "fsl,p5020-esdhc", "fsl,esdhc";
|
||||
fsl,iommu-parent = <&pamu1>;
|
||||
fsl,liodn-reg = <&guts 0x530>; /* eSDHCLIODNR */
|
||||
sdhci,auto-cmd12;
|
||||
|
||||
@@ -362,6 +362,7 @@
|
||||
|
||||
/include/ "qoriq-esdhc-0.dtsi"
|
||||
sdhc@114000 {
|
||||
compatible = "fsl,p5040-esdhc", "fsl,esdhc";
|
||||
fsl,iommu-parent = <&pamu2>;
|
||||
fsl,liodn-reg = <&guts 0x530>; /* eSDHCLIODNR */
|
||||
sdhci,auto-cmd12;
|
||||
|
||||
@@ -245,7 +245,7 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev,
|
||||
PIIX4_dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS &&
|
||||
PIIX4_dev->revision >= 0x41) ||
|
||||
(PIIX4_dev->vendor == PCI_VENDOR_ID_AMD &&
|
||||
PIIX4_dev->device == 0x790b &&
|
||||
PIIX4_dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS &&
|
||||
PIIX4_dev->revision >= 0x49))
|
||||
smb_en = 0x00;
|
||||
else
|
||||
@@ -545,7 +545,7 @@ static const struct pci_device_id piix4_ids[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SMBUS) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x790b) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_KERNCZ_SMBUS) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
|
||||
PCI_DEVICE_ID_SERVERWORKS_OSB4) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
|
||||
|
||||
@@ -913,6 +913,9 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req,
|
||||
if (!err)
|
||||
break;
|
||||
|
||||
/* Re-tune if needed */
|
||||
mmc_retune_recheck(card->host);
|
||||
|
||||
prev_cmd_status_valid = false;
|
||||
pr_err("%s: error %d sending status command, %sing\n",
|
||||
req->rq_disk->disk_name, err, retry ? "retry" : "abort");
|
||||
@@ -1204,6 +1207,7 @@ static int mmc_blk_err_check(struct mmc_card *card,
|
||||
mmc_active);
|
||||
struct mmc_blk_request *brq = &mq_mrq->brq;
|
||||
struct request *req = mq_mrq->req;
|
||||
int need_retune = card->host->need_retune;
|
||||
int ecc_err = 0, gen_err = 0;
|
||||
|
||||
/*
|
||||
@@ -1271,6 +1275,12 @@ static int mmc_blk_err_check(struct mmc_card *card,
|
||||
}
|
||||
|
||||
if (brq->data.error) {
|
||||
if (need_retune && !brq->retune_retry_done) {
|
||||
pr_info("%s: retrying because a re-tune was needed\n",
|
||||
req->rq_disk->disk_name);
|
||||
brq->retune_retry_done = 1;
|
||||
return MMC_BLK_RETRY;
|
||||
}
|
||||
pr_err("%s: error %d transferring data, sector %u, nr %u, cmd response %#x, card status %#x\n",
|
||||
req->rq_disk->disk_name, brq->data.error,
|
||||
(unsigned)blk_rq_pos(req),
|
||||
@@ -1830,7 +1840,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
|
||||
struct mmc_blk_data *md = mq->data;
|
||||
struct mmc_card *card = md->queue.card;
|
||||
struct mmc_blk_request *brq = &mq->mqrq_cur->brq;
|
||||
int ret = 1, disable_multi = 0, retry = 0, type;
|
||||
int ret = 1, disable_multi = 0, retry = 0, type, retune_retry_done = 0;
|
||||
enum mmc_blk_status status;
|
||||
struct mmc_queue_req *mq_rq;
|
||||
struct request *req = rqc;
|
||||
@@ -1910,10 +1920,13 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
|
||||
break;
|
||||
case MMC_BLK_CMD_ERR:
|
||||
ret = mmc_blk_cmd_err(md, card, brq, req, ret);
|
||||
if (!mmc_blk_reset(md, card->host, type))
|
||||
break;
|
||||
goto cmd_abort;
|
||||
if (mmc_blk_reset(md, card->host, type))
|
||||
goto cmd_abort;
|
||||
if (!ret)
|
||||
goto start_new_req;
|
||||
break;
|
||||
case MMC_BLK_RETRY:
|
||||
retune_retry_done = brq->retune_retry_done;
|
||||
if (retry++ < 5)
|
||||
break;
|
||||
/* Fall through */
|
||||
@@ -1976,6 +1989,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
|
||||
mmc_start_req(card->host,
|
||||
&mq_rq->mmc_active, NULL);
|
||||
}
|
||||
mq_rq->brq.retune_retry_done = retune_retry_done;
|
||||
}
|
||||
} while (ret);
|
||||
|
||||
@@ -2217,7 +2231,8 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card)
|
||||
* The CSD capacity field is in units of read_blkbits.
|
||||
* set_capacity takes units of 512 bytes.
|
||||
*/
|
||||
size = card->csd.capacity << (card->csd.read_blkbits - 9);
|
||||
size = (typeof(sector_t))card->csd.capacity
|
||||
<< (card->csd.read_blkbits - 9);
|
||||
}
|
||||
|
||||
return mmc_blk_alloc_req(card, &card->dev, size, false, NULL,
|
||||
|
||||
+16
-88
@@ -268,8 +268,6 @@ static int mmc_test_wait_busy(struct mmc_test_card *test)
|
||||
static int mmc_test_buffer_transfer(struct mmc_test_card *test,
|
||||
u8 *buffer, unsigned addr, unsigned blksz, int write)
|
||||
{
|
||||
int ret;
|
||||
|
||||
struct mmc_request mrq = {0};
|
||||
struct mmc_command cmd = {0};
|
||||
struct mmc_command stop = {0};
|
||||
@@ -292,11 +290,7 @@ static int mmc_test_buffer_transfer(struct mmc_test_card *test,
|
||||
if (data.error)
|
||||
return data.error;
|
||||
|
||||
ret = mmc_test_wait_busy(test);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
return mmc_test_wait_busy(test);
|
||||
}
|
||||
|
||||
static void mmc_test_free_mem(struct mmc_test_mem *mem)
|
||||
@@ -826,9 +820,7 @@ static int mmc_test_nonblock_transfer(struct mmc_test_card *test,
|
||||
mmc_test_nonblock_reset(&mrq1, &cmd1,
|
||||
&stop1, &data1);
|
||||
}
|
||||
done_areq = cur_areq;
|
||||
cur_areq = other_areq;
|
||||
other_areq = done_areq;
|
||||
swap(cur_areq, other_areq);
|
||||
dev_addr += blocks;
|
||||
}
|
||||
|
||||
@@ -994,11 +986,7 @@ static int mmc_test_basic_write(struct mmc_test_card *test)
|
||||
|
||||
sg_init_one(&sg, test->buffer, 512);
|
||||
|
||||
ret = mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
return mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 1);
|
||||
}
|
||||
|
||||
static int mmc_test_basic_read(struct mmc_test_card *test)
|
||||
@@ -1012,44 +1000,29 @@ static int mmc_test_basic_read(struct mmc_test_card *test)
|
||||
|
||||
sg_init_one(&sg, test->buffer, 512);
|
||||
|
||||
ret = mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
return mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 0);
|
||||
}
|
||||
|
||||
static int mmc_test_verify_write(struct mmc_test_card *test)
|
||||
{
|
||||
int ret;
|
||||
struct scatterlist sg;
|
||||
|
||||
sg_init_one(&sg, test->buffer, 512);
|
||||
|
||||
ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
return mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
|
||||
}
|
||||
|
||||
static int mmc_test_verify_read(struct mmc_test_card *test)
|
||||
{
|
||||
int ret;
|
||||
struct scatterlist sg;
|
||||
|
||||
sg_init_one(&sg, test->buffer, 512);
|
||||
|
||||
ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
return mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
|
||||
}
|
||||
|
||||
static int mmc_test_multi_write(struct mmc_test_card *test)
|
||||
{
|
||||
int ret;
|
||||
unsigned int size;
|
||||
struct scatterlist sg;
|
||||
|
||||
@@ -1066,16 +1039,11 @@ static int mmc_test_multi_write(struct mmc_test_card *test)
|
||||
|
||||
sg_init_one(&sg, test->buffer, size);
|
||||
|
||||
ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
return mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
|
||||
}
|
||||
|
||||
static int mmc_test_multi_read(struct mmc_test_card *test)
|
||||
{
|
||||
int ret;
|
||||
unsigned int size;
|
||||
struct scatterlist sg;
|
||||
|
||||
@@ -1092,11 +1060,7 @@ static int mmc_test_multi_read(struct mmc_test_card *test)
|
||||
|
||||
sg_init_one(&sg, test->buffer, size);
|
||||
|
||||
ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
return mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
|
||||
}
|
||||
|
||||
static int mmc_test_pow2_write(struct mmc_test_card *test)
|
||||
@@ -1263,11 +1227,7 @@ static int mmc_test_xfersize_write(struct mmc_test_card *test)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mmc_test_broken_transfer(test, 1, 512, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
return mmc_test_broken_transfer(test, 1, 512, 1);
|
||||
}
|
||||
|
||||
static int mmc_test_xfersize_read(struct mmc_test_card *test)
|
||||
@@ -1278,11 +1238,7 @@ static int mmc_test_xfersize_read(struct mmc_test_card *test)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mmc_test_broken_transfer(test, 1, 512, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
return mmc_test_broken_transfer(test, 1, 512, 0);
|
||||
}
|
||||
|
||||
static int mmc_test_multi_xfersize_write(struct mmc_test_card *test)
|
||||
@@ -1296,11 +1252,7 @@ static int mmc_test_multi_xfersize_write(struct mmc_test_card *test)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mmc_test_broken_transfer(test, 2, 512, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
return mmc_test_broken_transfer(test, 2, 512, 1);
|
||||
}
|
||||
|
||||
static int mmc_test_multi_xfersize_read(struct mmc_test_card *test)
|
||||
@@ -1314,48 +1266,33 @@ static int mmc_test_multi_xfersize_read(struct mmc_test_card *test)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mmc_test_broken_transfer(test, 2, 512, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
return mmc_test_broken_transfer(test, 2, 512, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HIGHMEM
|
||||
|
||||
static int mmc_test_write_high(struct mmc_test_card *test)
|
||||
{
|
||||
int ret;
|
||||
struct scatterlist sg;
|
||||
|
||||
sg_init_table(&sg, 1);
|
||||
sg_set_page(&sg, test->highmem, 512, 0);
|
||||
|
||||
ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
return mmc_test_transfer(test, &sg, 1, 0, 1, 512, 1);
|
||||
}
|
||||
|
||||
static int mmc_test_read_high(struct mmc_test_card *test)
|
||||
{
|
||||
int ret;
|
||||
struct scatterlist sg;
|
||||
|
||||
sg_init_table(&sg, 1);
|
||||
sg_set_page(&sg, test->highmem, 512, 0);
|
||||
|
||||
ret = mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
return mmc_test_transfer(test, &sg, 1, 0, 1, 512, 0);
|
||||
}
|
||||
|
||||
static int mmc_test_multi_write_high(struct mmc_test_card *test)
|
||||
{
|
||||
int ret;
|
||||
unsigned int size;
|
||||
struct scatterlist sg;
|
||||
|
||||
@@ -1373,16 +1310,11 @@ static int mmc_test_multi_write_high(struct mmc_test_card *test)
|
||||
sg_init_table(&sg, 1);
|
||||
sg_set_page(&sg, test->highmem, size, 0);
|
||||
|
||||
ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
return mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1);
|
||||
}
|
||||
|
||||
static int mmc_test_multi_read_high(struct mmc_test_card *test)
|
||||
{
|
||||
int ret;
|
||||
unsigned int size;
|
||||
struct scatterlist sg;
|
||||
|
||||
@@ -1400,11 +1332,7 @@ static int mmc_test_multi_read_high(struct mmc_test_card *test)
|
||||
sg_init_table(&sg, 1);
|
||||
sg_set_page(&sg, test->highmem, size, 0);
|
||||
|
||||
ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
return mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
@@ -56,7 +56,6 @@ static int mmc_queue_thread(void *d)
|
||||
down(&mq->thread_sem);
|
||||
do {
|
||||
struct request *req = NULL;
|
||||
struct mmc_queue_req *tmp;
|
||||
unsigned int cmd_flags = 0;
|
||||
|
||||
spin_lock_irq(q->queue_lock);
|
||||
@@ -69,6 +68,7 @@ static int mmc_queue_thread(void *d)
|
||||
set_current_state(TASK_RUNNING);
|
||||
cmd_flags = req ? req->cmd_flags : 0;
|
||||
mq->issue_fn(mq, req);
|
||||
cond_resched();
|
||||
if (mq->flags & MMC_QUEUE_NEW_REQUEST) {
|
||||
mq->flags &= ~MMC_QUEUE_NEW_REQUEST;
|
||||
continue; /* fetch again */
|
||||
@@ -86,9 +86,7 @@ static int mmc_queue_thread(void *d)
|
||||
|
||||
mq->mqrq_prev->brq.mrq.data = NULL;
|
||||
mq->mqrq_prev->req = NULL;
|
||||
tmp = mq->mqrq_prev;
|
||||
mq->mqrq_prev = mq->mqrq_cur;
|
||||
mq->mqrq_cur = tmp;
|
||||
swap(mq->mqrq_prev, mq->mqrq_cur);
|
||||
} else {
|
||||
if (kthread_should_stop()) {
|
||||
set_current_state(TASK_RUNNING);
|
||||
|
||||
@@ -12,6 +12,7 @@ struct mmc_blk_request {
|
||||
struct mmc_command cmd;
|
||||
struct mmc_command stop;
|
||||
struct mmc_data data;
|
||||
int retune_retry_done;
|
||||
};
|
||||
|
||||
enum mmc_packed_type {
|
||||
|
||||
+90
-10
@@ -133,6 +133,12 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
|
||||
struct mmc_command *cmd = mrq->cmd;
|
||||
int err = cmd->error;
|
||||
|
||||
/* Flag re-tuning needed on CRC errors */
|
||||
if (err == -EILSEQ || (mrq->sbc && mrq->sbc->error == -EILSEQ) ||
|
||||
(mrq->data && mrq->data->error == -EILSEQ) ||
|
||||
(mrq->stop && mrq->stop->error == -EILSEQ))
|
||||
mmc_retune_needed(host);
|
||||
|
||||
if (err && cmd->retries && mmc_host_is_spi(host)) {
|
||||
if (cmd->resp[0] & R1_SPI_ILLEGAL_COMMAND)
|
||||
cmd->retries = 0;
|
||||
@@ -186,12 +192,29 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
|
||||
|
||||
EXPORT_SYMBOL(mmc_request_done);
|
||||
|
||||
static void __mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Assumes host controller has been runtime resumed by mmc_claim_host */
|
||||
err = mmc_retune(host);
|
||||
if (err) {
|
||||
mrq->cmd->error = err;
|
||||
mmc_request_done(host, mrq);
|
||||
return;
|
||||
}
|
||||
|
||||
host->ops->request(host, mrq);
|
||||
}
|
||||
|
||||
static int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
|
||||
{
|
||||
#ifdef CONFIG_MMC_DEBUG
|
||||
unsigned int i, sz;
|
||||
struct scatterlist *sg;
|
||||
#endif
|
||||
mmc_retune_hold(host);
|
||||
|
||||
if (mmc_card_removed(host->card))
|
||||
return -ENOMEDIUM;
|
||||
|
||||
@@ -252,7 +275,7 @@ static int mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
|
||||
}
|
||||
mmc_host_clk_hold(host);
|
||||
led_trigger_event(host->led, LED_FULL);
|
||||
host->ops->request(host, mrq);
|
||||
__mmc_start_request(host, mrq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -301,12 +324,15 @@ void mmc_start_bkops(struct mmc_card *card, bool from_exception)
|
||||
use_busy_signal = false;
|
||||
}
|
||||
|
||||
mmc_retune_hold(card->host);
|
||||
|
||||
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
|
||||
EXT_CSD_BKOPS_START, 1, timeout,
|
||||
use_busy_signal, true, false);
|
||||
if (err) {
|
||||
pr_warn("%s: Error %d starting bkops\n",
|
||||
mmc_hostname(card->host), err);
|
||||
mmc_retune_release(card->host);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -317,6 +343,8 @@ void mmc_start_bkops(struct mmc_card *card, bool from_exception)
|
||||
*/
|
||||
if (!use_busy_signal)
|
||||
mmc_card_set_doing_bkops(card);
|
||||
else
|
||||
mmc_retune_release(card->host);
|
||||
out:
|
||||
mmc_release_host(card->host);
|
||||
}
|
||||
@@ -417,22 +445,22 @@ static int mmc_wait_for_data_req_done(struct mmc_host *host,
|
||||
host->areq);
|
||||
break; /* return err */
|
||||
} else {
|
||||
mmc_retune_recheck(host);
|
||||
pr_info("%s: req failed (CMD%u): %d, retrying...\n",
|
||||
mmc_hostname(host),
|
||||
cmd->opcode, cmd->error);
|
||||
cmd->retries--;
|
||||
cmd->error = 0;
|
||||
host->ops->request(host, mrq);
|
||||
__mmc_start_request(host, mrq);
|
||||
continue; /* wait for done/new event again */
|
||||
}
|
||||
} else if (context_info->is_new_req) {
|
||||
context_info->is_new_req = false;
|
||||
if (!next_req) {
|
||||
err = MMC_BLK_NEW_REQUEST;
|
||||
break; /* return err */
|
||||
}
|
||||
if (!next_req)
|
||||
return MMC_BLK_NEW_REQUEST;
|
||||
}
|
||||
}
|
||||
mmc_retune_release(host);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -467,12 +495,16 @@ static void mmc_wait_for_req_done(struct mmc_host *host,
|
||||
mmc_card_removed(host->card))
|
||||
break;
|
||||
|
||||
mmc_retune_recheck(host);
|
||||
|
||||
pr_debug("%s: req failed (CMD%u): %d, retrying...\n",
|
||||
mmc_hostname(host), cmd->opcode, cmd->error);
|
||||
cmd->retries--;
|
||||
cmd->error = 0;
|
||||
host->ops->request(host, mrq);
|
||||
__mmc_start_request(host, mrq);
|
||||
}
|
||||
|
||||
mmc_retune_release(host);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -728,6 +760,7 @@ int mmc_stop_bkops(struct mmc_card *card)
|
||||
*/
|
||||
if (!err || (err == -EINVAL)) {
|
||||
mmc_card_clr_doing_bkops(card);
|
||||
mmc_retune_release(card->host);
|
||||
err = 0;
|
||||
}
|
||||
|
||||
@@ -1109,6 +1142,8 @@ int mmc_execute_tuning(struct mmc_card *card)
|
||||
|
||||
if (err)
|
||||
pr_err("%s: tuning execution failed\n", mmc_hostname(host));
|
||||
else
|
||||
mmc_retune_enable(host);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -1140,6 +1175,8 @@ void mmc_set_bus_width(struct mmc_host *host, unsigned int width)
|
||||
*/
|
||||
void mmc_set_initial_state(struct mmc_host *host)
|
||||
{
|
||||
mmc_retune_disable(host);
|
||||
|
||||
if (mmc_host_is_spi(host))
|
||||
host->ios.chip_select = MMC_CS_HIGH;
|
||||
else
|
||||
@@ -1147,6 +1184,7 @@ void mmc_set_initial_state(struct mmc_host *host)
|
||||
host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
|
||||
host->ios.bus_width = MMC_BUS_WIDTH_1;
|
||||
host->ios.timing = MMC_TIMING_LEGACY;
|
||||
host->ios.drv_type = 0;
|
||||
|
||||
mmc_set_ios(host);
|
||||
}
|
||||
@@ -1551,8 +1589,8 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr)
|
||||
goto power_cycle;
|
||||
}
|
||||
|
||||
/* Keep clock gated for at least 5 ms */
|
||||
mmc_delay(5);
|
||||
/* Keep clock gated for at least 10 ms, though spec only says 5 ms */
|
||||
mmc_delay(10);
|
||||
host->ios.clock = clock;
|
||||
mmc_set_ios(host);
|
||||
|
||||
@@ -1601,6 +1639,44 @@ void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type)
|
||||
mmc_host_clk_release(host);
|
||||
}
|
||||
|
||||
int mmc_select_drive_strength(struct mmc_card *card, unsigned int max_dtr,
|
||||
int card_drv_type, int *drv_type)
|
||||
{
|
||||
struct mmc_host *host = card->host;
|
||||
int host_drv_type = SD_DRIVER_TYPE_B;
|
||||
int drive_strength;
|
||||
|
||||
*drv_type = 0;
|
||||
|
||||
if (!host->ops->select_drive_strength)
|
||||
return 0;
|
||||
|
||||
/* Use SD definition of driver strength for hosts */
|
||||
if (host->caps & MMC_CAP_DRIVER_TYPE_A)
|
||||
host_drv_type |= SD_DRIVER_TYPE_A;
|
||||
|
||||
if (host->caps & MMC_CAP_DRIVER_TYPE_C)
|
||||
host_drv_type |= SD_DRIVER_TYPE_C;
|
||||
|
||||
if (host->caps & MMC_CAP_DRIVER_TYPE_D)
|
||||
host_drv_type |= SD_DRIVER_TYPE_D;
|
||||
|
||||
/*
|
||||
* The drive strength that the hardware can support
|
||||
* depends on the board design. Pass the appropriate
|
||||
* information and let the hardware specific code
|
||||
* return what is possible given the options
|
||||
*/
|
||||
mmc_host_clk_hold(host);
|
||||
drive_strength = host->ops->select_drive_strength(card, max_dtr,
|
||||
host_drv_type,
|
||||
card_drv_type,
|
||||
drv_type);
|
||||
mmc_host_clk_release(host);
|
||||
|
||||
return drive_strength;
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply power to the MMC stack. This is a two-stage process.
|
||||
* First, we enable power to the card without the clock running.
|
||||
@@ -1970,6 +2046,8 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
|
||||
unsigned long timeout;
|
||||
int err;
|
||||
|
||||
mmc_retune_hold(card->host);
|
||||
|
||||
/*
|
||||
* qty is used to calculate the erase timeout which depends on how many
|
||||
* erase groups (or allocation units in SD terminology) are affected.
|
||||
@@ -2073,6 +2151,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from,
|
||||
} while (!(cmd.resp[0] & R1_READY_FOR_DATA) ||
|
||||
(R1_CURRENT_STATE(cmd.resp[0]) == R1_STATE_PRG));
|
||||
out:
|
||||
mmc_retune_release(card->host);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -2331,7 +2410,8 @@ int mmc_hw_reset(struct mmc_host *host)
|
||||
ret = host->bus_ops->reset(host);
|
||||
mmc_bus_put(host);
|
||||
|
||||
pr_warn("%s: tried to reset card\n", mmc_hostname(host));
|
||||
if (ret != -EOPNOTSUPP)
|
||||
pr_warn("%s: tried to reset card\n", mmc_hostname(host));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -50,6 +50,8 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, u32 ocr);
|
||||
int __mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage);
|
||||
void mmc_set_timing(struct mmc_host *host, unsigned int timing);
|
||||
void mmc_set_driver_type(struct mmc_host *host, unsigned int drv_type);
|
||||
int mmc_select_drive_strength(struct mmc_card *card, unsigned int max_dtr,
|
||||
int card_drv_type, int *drv_type);
|
||||
void mmc_power_up(struct mmc_host *host, u32 ocr);
|
||||
void mmc_power_off(struct mmc_host *host);
|
||||
void mmc_power_cycle(struct mmc_host *host, u32 ocr);
|
||||
@@ -88,6 +90,8 @@ void mmc_remove_card_debugfs(struct mmc_card *card);
|
||||
void mmc_init_context_info(struct mmc_host *host);
|
||||
|
||||
int mmc_execute_tuning(struct mmc_card *card);
|
||||
int mmc_hs200_to_hs400(struct mmc_card *card);
|
||||
int mmc_hs400_to_hs200(struct mmc_card *card);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user