MMC core:
- Fix driver strength selection when selecting hs400es - Delete bounce buffer handling: This change fixes a problem related to how bounce buffers are being allocated. However, instead of trying to fix that, let's just remove the mmc bounce buffer code altogether, as it has practically no use. MMC host: - meson-gx: A couple of fixes related to clock/phase/tuning - sdhci-xenon: Fix clock resource by adding an optional bus clock -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJZ2IGlAAoJEP4mhCVzWIwpi5gP/2dyF4FOK02BS24iV5LjElVV TkwpfNWDYguU9eBwCSrDZnCBsfeKgRobpTlre5qtNqGK2YqAwEO9n5lsZQL8HG/6 8LyVKSy9a7DWbuiK58dvswHKabjeZXZo1JdBx1JONTSfezNGGL5ZvyiDS7mHWv10 MsX+VukX31kFmS1HOd85Ayhdz9NlYZjnNSfmUN8UMuGMMysV007icwp8QX1uwW1s 2uPS0DFdtOlCoSs1ln6cyQMSoRZjRJ5Dm/SUFvRec4X7LC3ORxVbBXtbxtDGO8dS 6TIZHPILMpTHJcah/ONAk1LTXHO5Wt+x5o6vkca6uaEQEnvyUhKqK2NpwXCINRit OW+eJkAPv4J1a6/geZ99C7V+SDCCMsHeRrzfWxO1wkj/2ptu2OKtLPPJst2lLYgU QEXTgW920SxSWvWQaXcBmgkGZ67cyw3h2pI09QsmZJ9M4jmQpyZVIGWHgfsMFRkj iwtzuRL15qqnQqrs62eWJN383/b+BYfKzTnilVWExs+ozcpjYMYxYTGFTOKC1YV1 yeV+qL60gaK41HobWMJnbv0ckaPTLGZ1oOgB6F9OX6fGZz0LBh1yiOjYG1j66fwb KgDzN5sX4Ab/gDOT8zH1G8fGLYGBLDZMciuXrZfYf+mzJF8rpTI0he8BUwJm6KGC YJ+kW1MnnWATW+U63hRs =0WJ+ -----END PGP SIGNATURE----- Merge tag 'mmc-v4.14-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc Pull MMC fixes from Ulf Hansson: "MMC core: - Fix driver strength selection when selecting hs400es - Delete bounce buffer handling: This change fixes a problem related to how bounce buffers are being allocated. However, instead of trying to fix that, let's just remove the mmc bounce buffer code altogether, as it has practically no use. MMC host: - meson-gx: A couple of fixes related to clock/phase/tuning - sdhci-xenon: Fix clock resource by adding an optional bus clock" * tag 'mmc-v4.14-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: mmc: sdhci-xenon: Fix clock resource by adding an optional bus clock mmc: meson-gx: include tx phase in the tuning process mmc: meson-gx: fix rx phase reset mmc: meson-gx: make sure the clock is rounded down mmc: Delete bounce buffer handling mmc: core: add driver strength selection when selecting hs400es
This commit is contained in:
commit
031b814030
|
@ -16,11 +16,13 @@ Required Properties:
|
|||
|
||||
- clocks:
|
||||
Array of clocks required for SDHC.
|
||||
Require at least input clock for Xenon IP core.
|
||||
Require at least input clock for Xenon IP core. For Armada AP806 and
|
||||
CP110, the AXI clock is also mandatory.
|
||||
|
||||
- clock-names:
|
||||
Array of names corresponding to clocks property.
|
||||
The input clock for Xenon IP core should be named as "core".
|
||||
The input clock for the AXI bus must be named as "axi".
|
||||
|
||||
- reg:
|
||||
* For "marvell,armada-3700-sdhci", two register areas.
|
||||
|
@ -106,8 +108,8 @@ Example:
|
|||
compatible = "marvell,armada-ap806-sdhci";
|
||||
reg = <0xaa0000 0x1000>;
|
||||
interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>
|
||||
clocks = <&emmc_clk>;
|
||||
clock-names = "core";
|
||||
clocks = <&emmc_clk>,<&axi_clk>;
|
||||
clock-names = "core", "axi";
|
||||
bus-width = <4>;
|
||||
marvell,xenon-phy-slow-mode;
|
||||
marvell,xenon-tun-count = <11>;
|
||||
|
@ -126,8 +128,8 @@ Example:
|
|||
interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>
|
||||
vqmmc-supply = <&sd_vqmmc_regulator>;
|
||||
vmmc-supply = <&sd_vmmc_regulator>;
|
||||
clocks = <&sdclk>;
|
||||
clock-names = "core";
|
||||
clocks = <&sdclk>, <&axi_clk>;
|
||||
clock-names = "core", "axi";
|
||||
bus-width = <4>;
|
||||
marvell,xenon-tun-count = <9>;
|
||||
};
|
||||
|
|
|
@ -1634,8 +1634,6 @@ static void mmc_blk_data_prep(struct mmc_queue *mq, struct mmc_queue_req *mqrq,
|
|||
}
|
||||
|
||||
mqrq->areq.mrq = &brq->mrq;
|
||||
|
||||
mmc_queue_bounce_pre(mqrq);
|
||||
}
|
||||
|
||||
static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
|
||||
|
@ -1829,7 +1827,6 @@ static void mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *new_req)
|
|||
brq = &mq_rq->brq;
|
||||
old_req = mmc_queue_req_to_req(mq_rq);
|
||||
type = rq_data_dir(old_req) == READ ? MMC_BLK_READ : MMC_BLK_WRITE;
|
||||
mmc_queue_bounce_post(mq_rq);
|
||||
|
||||
switch (status) {
|
||||
case MMC_BLK_SUCCESS:
|
||||
|
|
|
@ -1286,6 +1286,23 @@ int mmc_hs400_to_hs200(struct mmc_card *card)
|
|||
return err;
|
||||
}
|
||||
|
||||
static void mmc_select_driver_type(struct mmc_card *card)
|
||||
{
|
||||
int card_drv_type, drive_strength, drv_type;
|
||||
|
||||
card_drv_type = card->ext_csd.raw_driver_strength |
|
||||
mmc_driver_type_mask(0);
|
||||
|
||||
drive_strength = mmc_select_drive_strength(card,
|
||||
card->ext_csd.hs200_max_dtr,
|
||||
card_drv_type, &drv_type);
|
||||
|
||||
card->drive_strength = drive_strength;
|
||||
|
||||
if (drv_type)
|
||||
mmc_set_driver_type(card->host, drv_type);
|
||||
}
|
||||
|
||||
static int mmc_select_hs400es(struct mmc_card *card)
|
||||
{
|
||||
struct mmc_host *host = card->host;
|
||||
|
@ -1341,6 +1358,8 @@ static int mmc_select_hs400es(struct mmc_card *card)
|
|||
goto out_err;
|
||||
}
|
||||
|
||||
mmc_select_driver_type(card);
|
||||
|
||||
/* Switch card to HS400 */
|
||||
val = EXT_CSD_TIMING_HS400 |
|
||||
card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
|
||||
|
@ -1374,23 +1393,6 @@ static int mmc_select_hs400es(struct mmc_card *card)
|
|||
return err;
|
||||
}
|
||||
|
||||
static void mmc_select_driver_type(struct mmc_card *card)
|
||||
{
|
||||
int card_drv_type, drive_strength, drv_type;
|
||||
|
||||
card_drv_type = card->ext_csd.raw_driver_strength |
|
||||
mmc_driver_type_mask(0);
|
||||
|
||||
drive_strength = mmc_select_drive_strength(card,
|
||||
card->ext_csd.hs200_max_dtr,
|
||||
card_drv_type, &drv_type);
|
||||
|
||||
card->drive_strength = drive_strength;
|
||||
|
||||
if (drv_type)
|
||||
mmc_set_driver_type(card->host, drv_type);
|
||||
}
|
||||
|
||||
/*
|
||||
* For device supporting HS200 mode, the following sequence
|
||||
* should be done before executing the tuning process.
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
#include "core.h"
|
||||
#include "card.h"
|
||||
|
||||
#define MMC_QUEUE_BOUNCESZ 65536
|
||||
|
||||
/*
|
||||
* Prepare a MMC request. This just filters out odd stuff.
|
||||
*/
|
||||
|
@ -150,26 +148,6 @@ static void mmc_queue_setup_discard(struct request_queue *q,
|
|||
queue_flag_set_unlocked(QUEUE_FLAG_SECERASE, q);
|
||||
}
|
||||
|
||||
static unsigned int mmc_queue_calc_bouncesz(struct mmc_host *host)
|
||||
{
|
||||
unsigned int bouncesz = MMC_QUEUE_BOUNCESZ;
|
||||
|
||||
if (host->max_segs != 1 || (host->caps & MMC_CAP_NO_BOUNCE_BUFF))
|
||||
return 0;
|
||||
|
||||
if (bouncesz > host->max_req_size)
|
||||
bouncesz = host->max_req_size;
|
||||
if (bouncesz > host->max_seg_size)
|
||||
bouncesz = host->max_seg_size;
|
||||
if (bouncesz > host->max_blk_count * 512)
|
||||
bouncesz = host->max_blk_count * 512;
|
||||
|
||||
if (bouncesz <= 512)
|
||||
return 0;
|
||||
|
||||
return bouncesz;
|
||||
}
|
||||
|
||||
/**
|
||||
* mmc_init_request() - initialize the MMC-specific per-request data
|
||||
* @q: the request queue
|
||||
|
@ -184,26 +162,9 @@ static int mmc_init_request(struct request_queue *q, struct request *req,
|
|||
struct mmc_card *card = mq->card;
|
||||
struct mmc_host *host = card->host;
|
||||
|
||||
if (card->bouncesz) {
|
||||
mq_rq->bounce_buf = kmalloc(card->bouncesz, gfp);
|
||||
if (!mq_rq->bounce_buf)
|
||||
return -ENOMEM;
|
||||
if (card->bouncesz > 512) {
|
||||
mq_rq->sg = mmc_alloc_sg(1, gfp);
|
||||
if (!mq_rq->sg)
|
||||
return -ENOMEM;
|
||||
mq_rq->bounce_sg = mmc_alloc_sg(card->bouncesz / 512,
|
||||
gfp);
|
||||
if (!mq_rq->bounce_sg)
|
||||
return -ENOMEM;
|
||||
}
|
||||
} else {
|
||||
mq_rq->bounce_buf = NULL;
|
||||
mq_rq->bounce_sg = NULL;
|
||||
mq_rq->sg = mmc_alloc_sg(host->max_segs, gfp);
|
||||
if (!mq_rq->sg)
|
||||
return -ENOMEM;
|
||||
}
|
||||
mq_rq->sg = mmc_alloc_sg(host->max_segs, gfp);
|
||||
if (!mq_rq->sg)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -212,13 +173,6 @@ static void mmc_exit_request(struct request_queue *q, struct request *req)
|
|||
{
|
||||
struct mmc_queue_req *mq_rq = req_to_mmc_queue_req(req);
|
||||
|
||||
/* It is OK to kfree(NULL) so this will be smooth */
|
||||
kfree(mq_rq->bounce_sg);
|
||||
mq_rq->bounce_sg = NULL;
|
||||
|
||||
kfree(mq_rq->bounce_buf);
|
||||
mq_rq->bounce_buf = NULL;
|
||||
|
||||
kfree(mq_rq->sg);
|
||||
mq_rq->sg = NULL;
|
||||
}
|
||||
|
@ -242,12 +196,6 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
|
|||
if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
|
||||
limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT;
|
||||
|
||||
/*
|
||||
* mmc_init_request() depends on card->bouncesz so it must be calculated
|
||||
* before blk_init_allocated_queue() starts allocating requests.
|
||||
*/
|
||||
card->bouncesz = mmc_queue_calc_bouncesz(host);
|
||||
|
||||
mq->card = card;
|
||||
mq->queue = blk_alloc_queue(GFP_KERNEL);
|
||||
if (!mq->queue)
|
||||
|
@ -271,17 +219,11 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
|
|||
if (mmc_can_erase(card))
|
||||
mmc_queue_setup_discard(mq->queue, card);
|
||||
|
||||
if (card->bouncesz) {
|
||||
blk_queue_max_hw_sectors(mq->queue, card->bouncesz / 512);
|
||||
blk_queue_max_segments(mq->queue, card->bouncesz / 512);
|
||||
blk_queue_max_segment_size(mq->queue, card->bouncesz);
|
||||
} else {
|
||||
blk_queue_bounce_limit(mq->queue, limit);
|
||||
blk_queue_max_hw_sectors(mq->queue,
|
||||
min(host->max_blk_count, host->max_req_size / 512));
|
||||
blk_queue_max_segments(mq->queue, host->max_segs);
|
||||
blk_queue_max_segment_size(mq->queue, host->max_seg_size);
|
||||
}
|
||||
blk_queue_bounce_limit(mq->queue, limit);
|
||||
blk_queue_max_hw_sectors(mq->queue,
|
||||
min(host->max_blk_count, host->max_req_size / 512));
|
||||
blk_queue_max_segments(mq->queue, host->max_segs);
|
||||
blk_queue_max_segment_size(mq->queue, host->max_seg_size);
|
||||
|
||||
sema_init(&mq->thread_sem, 1);
|
||||
|
||||
|
@ -370,56 +312,7 @@ void mmc_queue_resume(struct mmc_queue *mq)
|
|||
*/
|
||||
unsigned int mmc_queue_map_sg(struct mmc_queue *mq, struct mmc_queue_req *mqrq)
|
||||
{
|
||||
unsigned int sg_len;
|
||||
size_t buflen;
|
||||
struct scatterlist *sg;
|
||||
struct request *req = mmc_queue_req_to_req(mqrq);
|
||||
int i;
|
||||
|
||||
if (!mqrq->bounce_buf)
|
||||
return blk_rq_map_sg(mq->queue, req, mqrq->sg);
|
||||
|
||||
sg_len = blk_rq_map_sg(mq->queue, req, mqrq->bounce_sg);
|
||||
|
||||
mqrq->bounce_sg_len = sg_len;
|
||||
|
||||
buflen = 0;
|
||||
for_each_sg(mqrq->bounce_sg, sg, sg_len, i)
|
||||
buflen += sg->length;
|
||||
|
||||
sg_init_one(mqrq->sg, mqrq->bounce_buf, buflen);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If writing, bounce the data to the buffer before the request
|
||||
* is sent to the host driver
|
||||
*/
|
||||
void mmc_queue_bounce_pre(struct mmc_queue_req *mqrq)
|
||||
{
|
||||
if (!mqrq->bounce_buf)
|
||||
return;
|
||||
|
||||
if (rq_data_dir(mmc_queue_req_to_req(mqrq)) != WRITE)
|
||||
return;
|
||||
|
||||
sg_copy_to_buffer(mqrq->bounce_sg, mqrq->bounce_sg_len,
|
||||
mqrq->bounce_buf, mqrq->sg[0].length);
|
||||
}
|
||||
|
||||
/*
|
||||
* If reading, bounce the data from the buffer after the request
|
||||
* has been handled by the host driver
|
||||
*/
|
||||
void mmc_queue_bounce_post(struct mmc_queue_req *mqrq)
|
||||
{
|
||||
if (!mqrq->bounce_buf)
|
||||
return;
|
||||
|
||||
if (rq_data_dir(mmc_queue_req_to_req(mqrq)) != READ)
|
||||
return;
|
||||
|
||||
sg_copy_from_buffer(mqrq->bounce_sg, mqrq->bounce_sg_len,
|
||||
mqrq->bounce_buf, mqrq->sg[0].length);
|
||||
return blk_rq_map_sg(mq->queue, req, mqrq->sg);
|
||||
}
|
||||
|
|
|
@ -49,9 +49,6 @@ enum mmc_drv_op {
|
|||
struct mmc_queue_req {
|
||||
struct mmc_blk_request brq;
|
||||
struct scatterlist *sg;
|
||||
char *bounce_buf;
|
||||
struct scatterlist *bounce_sg;
|
||||
unsigned int bounce_sg_len;
|
||||
struct mmc_async_req areq;
|
||||
enum mmc_drv_op drv_op;
|
||||
int drv_op_result;
|
||||
|
@ -81,11 +78,8 @@ extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *,
|
|||
extern void mmc_cleanup_queue(struct mmc_queue *);
|
||||
extern void mmc_queue_suspend(struct mmc_queue *);
|
||||
extern void mmc_queue_resume(struct mmc_queue *);
|
||||
|
||||
extern unsigned int mmc_queue_map_sg(struct mmc_queue *,
|
||||
struct mmc_queue_req *);
|
||||
extern void mmc_queue_bounce_pre(struct mmc_queue_req *);
|
||||
extern void mmc_queue_bounce_post(struct mmc_queue_req *);
|
||||
|
||||
extern int mmc_access_rpmb(struct mmc_queue *);
|
||||
|
||||
|
|
|
@ -1038,7 +1038,7 @@ int cvm_mmc_of_slot_probe(struct device *dev, struct cvm_mmc_host *host)
|
|||
*/
|
||||
mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
|
||||
MMC_CAP_ERASE | MMC_CAP_CMD23 | MMC_CAP_POWER_OFF_CARD |
|
||||
MMC_CAP_3_3V_DDR | MMC_CAP_NO_BOUNCE_BUFF;
|
||||
MMC_CAP_3_3V_DDR;
|
||||
|
||||
if (host->use_sg)
|
||||
mmc->max_segs = 16;
|
||||
|
|
|
@ -531,8 +531,7 @@ static int meson_mmc_clk_init(struct meson_host *host)
|
|||
div->shift = __ffs(CLK_DIV_MASK);
|
||||
div->width = __builtin_popcountl(CLK_DIV_MASK);
|
||||
div->hw.init = &init;
|
||||
div->flags = (CLK_DIVIDER_ONE_BASED |
|
||||
CLK_DIVIDER_ROUND_CLOSEST);
|
||||
div->flags = CLK_DIVIDER_ONE_BASED;
|
||||
|
||||
clk = devm_clk_register(host->dev, &div->hw);
|
||||
if (WARN_ON(IS_ERR(clk)))
|
||||
|
@ -717,6 +716,22 @@ static int meson_mmc_clk_phase_tuning(struct mmc_host *mmc, u32 opcode,
|
|||
static int meson_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode)
|
||||
{
|
||||
struct meson_host *host = mmc_priv(mmc);
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* If this is the initial tuning, try to get a sane Rx starting
|
||||
* phase before doing the actual tuning.
|
||||
*/
|
||||
if (!mmc->doing_retune) {
|
||||
ret = meson_mmc_clk_phase_tuning(mmc, opcode, host->rx_clk);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = meson_mmc_clk_phase_tuning(mmc, opcode, host->tx_clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return meson_mmc_clk_phase_tuning(mmc, opcode, host->rx_clk);
|
||||
}
|
||||
|
@ -746,6 +761,11 @@ static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
|||
case MMC_POWER_UP:
|
||||
if (!IS_ERR(mmc->supply.vmmc))
|
||||
mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd);
|
||||
|
||||
/* Reset phases */
|
||||
clk_set_phase(host->rx_clk, 0);
|
||||
clk_set_phase(host->tx_clk, 270);
|
||||
|
||||
break;
|
||||
|
||||
case MMC_POWER_ON:
|
||||
|
@ -759,8 +779,6 @@ static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
|||
host->vqmmc_enabled = true;
|
||||
}
|
||||
|
||||
/* Reset rx phase */
|
||||
clk_set_phase(host->rx_clk, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -702,11 +702,7 @@ static int pxamci_probe(struct platform_device *pdev)
|
|||
|
||||
pxamci_init_ocr(host);
|
||||
|
||||
/*
|
||||
* This architecture used to disable bounce buffers through its
|
||||
* defconfig, now it is done at runtime as a host property.
|
||||
*/
|
||||
mmc->caps = MMC_CAP_NO_BOUNCE_BUFF;
|
||||
mmc->caps = 0;
|
||||
host->cmdat = 0;
|
||||
if (!cpu_is_pxa25x()) {
|
||||
mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
|
||||
|
|
|
@ -466,6 +466,7 @@ static int xenon_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct sdhci_pltfm_host *pltfm_host;
|
||||
struct sdhci_host *host;
|
||||
struct xenon_priv *priv;
|
||||
int err;
|
||||
|
||||
host = sdhci_pltfm_init(pdev, &sdhci_xenon_pdata,
|
||||
|
@ -474,6 +475,7 @@ static int xenon_probe(struct platform_device *pdev)
|
|||
return PTR_ERR(host);
|
||||
|
||||
pltfm_host = sdhci_priv(host);
|
||||
priv = sdhci_pltfm_priv(pltfm_host);
|
||||
|
||||
/*
|
||||
* Link Xenon specific mmc_host_ops function,
|
||||
|
@ -491,9 +493,20 @@ static int xenon_probe(struct platform_device *pdev)
|
|||
if (err)
|
||||
goto free_pltfm;
|
||||
|
||||
priv->axi_clk = devm_clk_get(&pdev->dev, "axi");
|
||||
if (IS_ERR(priv->axi_clk)) {
|
||||
err = PTR_ERR(priv->axi_clk);
|
||||
if (err == -EPROBE_DEFER)
|
||||
goto err_clk;
|
||||
} else {
|
||||
err = clk_prepare_enable(priv->axi_clk);
|
||||
if (err)
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
err = mmc_of_parse(host->mmc);
|
||||
if (err)
|
||||
goto err_clk;
|
||||
goto err_clk_axi;
|
||||
|
||||
sdhci_get_of_property(pdev);
|
||||
|
||||
|
@ -502,11 +515,11 @@ static int xenon_probe(struct platform_device *pdev)
|
|||
/* Xenon specific dt parse */
|
||||
err = xenon_probe_dt(pdev);
|
||||
if (err)
|
||||
goto err_clk;
|
||||
goto err_clk_axi;
|
||||
|
||||
err = xenon_sdhc_prepare(host);
|
||||
if (err)
|
||||
goto err_clk;
|
||||
goto err_clk_axi;
|
||||
|
||||
pm_runtime_get_noresume(&pdev->dev);
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
|
@ -527,6 +540,8 @@ static int xenon_probe(struct platform_device *pdev)
|
|||
pm_runtime_disable(&pdev->dev);
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
xenon_sdhc_unprepare(host);
|
||||
err_clk_axi:
|
||||
clk_disable_unprepare(priv->axi_clk);
|
||||
err_clk:
|
||||
clk_disable_unprepare(pltfm_host->clk);
|
||||
free_pltfm:
|
||||
|
@ -538,6 +553,7 @@ static int xenon_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct sdhci_host *host = platform_get_drvdata(pdev);
|
||||
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
|
||||
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
@ -546,7 +562,7 @@ static int xenon_remove(struct platform_device *pdev)
|
|||
sdhci_remove_host(host, 0);
|
||||
|
||||
xenon_sdhc_unprepare(host);
|
||||
|
||||
clk_disable_unprepare(priv->axi_clk);
|
||||
clk_disable_unprepare(pltfm_host->clk);
|
||||
|
||||
sdhci_pltfm_free(pdev);
|
||||
|
|
|
@ -83,6 +83,7 @@ struct xenon_priv {
|
|||
unsigned char bus_width;
|
||||
unsigned char timing;
|
||||
unsigned int clock;
|
||||
struct clk *axi_clk;
|
||||
|
||||
int phy_type;
|
||||
/*
|
||||
|
|
|
@ -316,7 +316,7 @@ struct mmc_host {
|
|||
#define MMC_CAP_UHS_SDR50 (1 << 18) /* Host supports UHS SDR50 mode */
|
||||
#define MMC_CAP_UHS_SDR104 (1 << 19) /* Host supports UHS SDR104 mode */
|
||||
#define MMC_CAP_UHS_DDR50 (1 << 20) /* Host supports UHS DDR50 mode */
|
||||
#define MMC_CAP_NO_BOUNCE_BUFF (1 << 21) /* Disable bounce buffers on host */
|
||||
/* (1 << 21) is free for reuse */
|
||||
#define MMC_CAP_DRIVER_TYPE_A (1 << 23) /* Host supports Driver Type A */
|
||||
#define MMC_CAP_DRIVER_TYPE_C (1 << 24) /* Host supports Driver Type C */
|
||||
#define MMC_CAP_DRIVER_TYPE_D (1 << 25) /* Host supports Driver Type D */
|
||||
|
|
Loading…
Reference in New Issue