project:build.sh: Added fastboot support; custom modifications to U-Boot and kernel implemented using patches.

project:cfg:BoardConfig_IPC: Added fastboot BoardConfig file and firmware post-scripts, distinguishing between
the BoardConfigs for Luckfox Pico Pro and Luckfox Pico Max. project:app: Added fastboot_client and rk_smart_door
for quick boot applications; updated rkipc app to adapt to the latest media library. media:samples: Added more
usage examples. media:rockit: Fixed bugs; removed support for retrieving data frames from VPSS. media:isp:
Updated rkaiq library and related tools to support connection to RKISP_Tuner. sysdrv:Makefile: Added support for
compiling drv_ko on Luckfox Pico Ultra W using Ubuntu; added support for custom root filesystem.
sysdrv:tools:board: Updated Buildroot optional mirror sources, updated some software versions, and stored device
tree files and configuration files that undergo multiple modifications for U-Boot and kernel separately.
sysdrv:source:mcu: Used RISC-V MCU SDK with RT-Thread system, mainly for initializing camera AE during quick
boot. sysdrv:source:uboot: Added support for fastboot; added high baud rate DDR bin for serial firmware upgrades.
sysdrv:source:kernel: Upgraded to version 5.10.160; increased NPU frequency for RV1106G3; added support for
fastboot.

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>
This commit is contained in:
luckfox-eng29
2024-08-21 10:05:47 +08:00
parent e79fd21975
commit 8f34c2760d
20902 changed files with 6567362 additions and 11248383 deletions

View File

@@ -2,7 +2,6 @@
#
# Makefile for the kernel mmc device drivers.
#
#subdir-ccflags-y := -DDEBUG
obj-$(CONFIG_MMC) += core/
obj-$(subst m,y,$(CONFIG_MMC)) += host/

View File

@@ -172,7 +172,7 @@ static inline int mmc_blk_part_switch(struct mmc_card *card,
unsigned int part_type);
static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
struct mmc_card *card,
int disable_multi,
int recovery_mode,
struct mmc_queue *mq);
static void mmc_blk_hsq_req_done(struct mmc_request *mrq);
@@ -415,7 +415,7 @@ static int mmc_blk_ioctl_copy_to_user(struct mmc_ioc_cmd __user *ic_ptr,
static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
u32 *resp_errs)
{
unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms);
unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms > 2000 ? 2000 : timeout_ms);
int err = 0;
u32 status;
@@ -1085,6 +1085,11 @@ static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
nr = blk_rq_sectors(req);
do {
unsigned int erase_arg = card->erase_arg;
if (mmc_card_broken_sd_discard(card))
erase_arg = SD_ERASE_ARG;
err = 0;
if (card->quirks & MMC_QUIRK_INAND_CMD38) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
@@ -1095,7 +1100,7 @@ static void mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
card->ext_csd.generic_cmd6_time);
}
if (!err)
err = mmc_erase(card, from, nr, card->erase_arg);
err = mmc_erase(card, from, nr, erase_arg);
} while (err == -EIO && !mmc_blk_reset(md, card->host, type));
if (err)
status = BLK_STS_IOERR;
@@ -1263,7 +1268,7 @@ static void mmc_blk_eval_resp_error(struct mmc_blk_request *brq)
}
static void mmc_blk_data_prep(struct mmc_queue *mq, struct mmc_queue_req *mqrq,
int disable_multi, bool *do_rel_wr_p,
int recovery_mode, bool *do_rel_wr_p,
bool *do_data_tag_p)
{
struct mmc_blk_data *md = mq->blkdata;
@@ -1329,12 +1334,12 @@ static void mmc_blk_data_prep(struct mmc_queue *mq, struct mmc_queue_req *mqrq,
brq->data.blocks--;
/*
* After a read error, we redo the request one sector
* After a read error, we redo the request one (native) sector
* at a time in order to accurately determine which
* sectors can be read successfully.
*/
if (disable_multi)
brq->data.blocks = 1;
if (recovery_mode)
brq->data.blocks = queue_physical_block_size(mq->queue) >> 9;
/*
* Some controllers have HW issues while operating
@@ -1460,8 +1465,7 @@ void mmc_blk_cqe_recovery(struct mmc_queue *mq)
err = mmc_cqe_recovery(host);
if (err)
mmc_blk_reset(mq->blkdata, host, MMC_BLK_CQE_RECOVERY);
else
mmc_blk_reset_success(mq->blkdata, MMC_BLK_CQE_RECOVERY);
mmc_blk_reset_success(mq->blkdata, MMC_BLK_CQE_RECOVERY);
pr_debug("%s: CQE recovery done\n", mmc_hostname(host));
}
@@ -1552,7 +1556,7 @@ static int mmc_blk_cqe_issue_rw_rq(struct mmc_queue *mq, struct request *req)
static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
struct mmc_card *card,
int disable_multi,
int recovery_mode,
struct mmc_queue *mq)
{
u32 readcmd, writecmd;
@@ -1561,7 +1565,7 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
struct mmc_blk_data *md = mq->blkdata;
bool do_rel_wr, do_data_tag;
mmc_blk_data_prep(mq, mqrq, disable_multi, &do_rel_wr, &do_data_tag);
mmc_blk_data_prep(mq, mqrq, recovery_mode, &do_rel_wr, &do_data_tag);
brq->mrq.cmd = &brq->cmd;
@@ -1652,7 +1656,7 @@ static int mmc_blk_fix_state(struct mmc_card *card, struct request *req)
#define MMC_READ_SINGLE_RETRIES 2
/* Single sector read during recovery */
/* Single (native) sector read during recovery */
static void mmc_blk_read_single(struct mmc_queue *mq, struct request *req)
{
struct mmc_queue_req *mqrq = req_to_mmc_queue_req(req);
@@ -1660,6 +1664,7 @@ static void mmc_blk_read_single(struct mmc_queue *mq, struct request *req)
struct mmc_card *card = mq->card;
struct mmc_host *host = card->host;
blk_status_t error = BLK_STS_OK;
size_t bytes_per_read = queue_physical_block_size(mq->queue);
do {
u32 status;
@@ -1694,13 +1699,13 @@ static void mmc_blk_read_single(struct mmc_queue *mq, struct request *req)
else
error = BLK_STS_OK;
} while (blk_update_request(req, error, 512));
} while (blk_update_request(req, error, bytes_per_read));
return;
error_exit:
mrq->data->bytes_xfered = 0;
blk_update_request(req, BLK_STS_IOERR, 512);
blk_update_request(req, BLK_STS_IOERR, bytes_per_read);
/* Let it try the remaining request again */
if (mqrq->retries > MMC_MAX_RETRIES - 1)
mqrq->retries = MMC_MAX_RETRIES - 1;
@@ -1776,8 +1781,15 @@ static void mmc_blk_mq_rw_recovery(struct mmc_queue *mq, struct request *req)
* bytes transferred to zero in that case.
*/
err = __mmc_send_status(card, &status, 0);
if (err || mmc_blk_status_error(req, status))
if (err || mmc_blk_status_error(req, status)) {
brq->data.bytes_xfered = 0;
if (mmc_card_sd(card) && !mmc_card_removed(card)) {
mmc_blk_reset_success(mq->blkdata, type);
if (!mmc_blk_reset(md, card->host, type))
return;
pr_err("%s: pre recovery failed!\n", req->rq_disk->disk_name);
}
}
mmc_retune_release(card->host);
@@ -1842,10 +1854,9 @@ static void mmc_blk_mq_rw_recovery(struct mmc_queue *mq, struct request *req)
return;
}
/* FIXME: Missing single sector read for large sector size */
if (!mmc_large_sector(card) && rq_data_dir(req) == READ &&
brq->data.blocks > 1) {
/* Read one sector at a time */
if (rq_data_dir(req) == READ && brq->data.blocks >
queue_physical_block_size(mq->queue) >> 9) {
/* Read one (native) sector at a time */
mmc_blk_read_single(mq, req);
return;
}

View File

@@ -70,6 +70,7 @@ struct mmc_fixup {
#define EXT_CSD_REV_ANY (-1u)
#define CID_MANFID_SANDISK 0x2
#define CID_MANFID_SANDISK_SD 0x3
#define CID_MANFID_ATP 0x9
#define CID_MANFID_TOSHIBA 0x11
#define CID_MANFID_MICRON 0x13
@@ -223,4 +224,9 @@ static inline int mmc_card_broken_hpi(const struct mmc_card *c)
return c->quirks & MMC_QUIRK_BROKEN_HPI;
}
static inline int mmc_card_broken_sd_discard(const struct mmc_card *c)
{
return c->quirks & MMC_QUIRK_BROKEN_SD_DISCARD;
}
#endif

View File

@@ -1131,7 +1131,13 @@ u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
mmc_power_cycle(host, ocr);
} else {
bit = fls(ocr) - 1;
ocr &= 3 << bit;
/*
* The bit variable represents the highest voltage bit set in
* the OCR register.
* To keep a range of 2 values (e.g. 3.2V/3.3V and 3.3V/3.4V),
* we must shift the mask '3' with (bit - 1).
*/
ocr &= 3 << (bit - 1);
if (bit != host->ios.vdd)
dev_warn(mmc_dev(host), "exceeding card's volts\n");
}
@@ -1537,6 +1543,11 @@ void mmc_init_erase(struct mmc_card *card)
card->pref_erase = 0;
}
static bool is_trim_arg(unsigned int arg)
{
return (arg & MMC_TRIM_OR_DISCARD_ARGS) && arg != MMC_DISCARD_ARG;
}
static unsigned int mmc_mmc_erase_timeout(struct mmc_card *card,
unsigned int arg, unsigned int qty)
{
@@ -1835,7 +1846,7 @@ int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr,
!(card->ext_csd.sec_feature_support & EXT_CSD_SEC_ER_EN))
return -EOPNOTSUPP;
if (mmc_card_mmc(card) && (arg & MMC_TRIM_ARGS) &&
if (mmc_card_mmc(card) && is_trim_arg(arg) &&
!(card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN))
return -EOPNOTSUPP;
@@ -1865,7 +1876,7 @@ int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr,
* identified by the card->eg_boundary flag.
*/
rem = card->erase_size - (from % card->erase_size);
if ((arg & MMC_TRIM_ARGS) && (card->eg_boundary) && (nr > rem)) {
if ((arg & MMC_TRIM_OR_DISCARD_ARGS) && card->eg_boundary && nr > rem) {
err = mmc_do_erase(card, from, from + rem - 1, arg);
from += rem;
if ((err) || (to <= from))
@@ -2061,7 +2072,7 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen)
}
EXPORT_SYMBOL(mmc_set_blocklen);
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
static void mmc_hw_reset_for_init(struct mmc_host *host)
{
mmc_pwrseq_reset(host);
@@ -2143,7 +2154,7 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
* Some eMMCs (with VCCQ always on) may not be reset after power up, so
* do a hardware reset if possible.
*/
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
mmc_hw_reset_for_init(host);
#endif

View File

@@ -67,7 +67,7 @@ static const unsigned int taac_mant[] = {
/*
* Given the decoded CSD structure, decode the raw CID to our CID structure.
*/
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
static int mmc_decode_cid(struct mmc_card *card)
{
u32 *resp = card->raw_cid;
@@ -666,7 +666,7 @@ out:
return err;
}
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
static void *mmc_tb_map_ecsd(phys_addr_t start, size_t len)
{
int i;
@@ -696,7 +696,7 @@ static int mmc_read_ext_csd(struct mmc_card *card)
{
u8 *ext_csd;
int err;
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
void *ecsd;
bool valid_ecsd = false;
bool valid_reserved = false;
@@ -707,7 +707,7 @@ static int mmc_read_ext_csd(struct mmc_card *card)
if (!mmc_can_ext_csd(card))
return 0;
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
mem = of_parse_phandle(dev->of_node, "memory-region-ecsd", 0);
if (mem) {
err = of_address_to_resource(mem, 0, &reg);
@@ -758,11 +758,11 @@ get_ecsd:
return err;
}
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
decode:
#endif
err = mmc_decode_ext_csd(card, ext_csd);
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
if (!valid_ecsd)
kfree(ext_csd);
else
@@ -777,7 +777,7 @@ decode:
return err;
}
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width)
{
u8 *bw_ext_csd;
@@ -1120,7 +1120,7 @@ int mmc_select_bus_width(struct mmc_card *card)
* compare ext_csd previously read in 1 bit mode
* against ext_csd at new bus width
*/
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST))
err = mmc_compare_ext_csds(card, bus_width);
else
@@ -1462,9 +1462,13 @@ static int mmc_select_hs400es(struct mmc_card *card)
goto out_err;
}
/*
* Bump to HS timing and frequency. Some cards don't handle
* SEND_STATUS reliably at the initial frequency.
*/
mmc_set_timing(host, MMC_TIMING_MMC_HS);
/* Set clock immediately after changing timing */
mmc_set_clock(host, card->ext_csd.hs_max_dtr);
mmc_set_bus_speed(card);
err = mmc_switch_status(card, true);
if (err)
@@ -1527,7 +1531,7 @@ out_err:
static int mmc_select_hs200(struct mmc_card *card)
{
struct mmc_host *host = card->host;
unsigned int old_timing, old_signal_voltage;
unsigned int old_timing, old_signal_voltage, old_clock;
int err = -EINVAL;
u8 val;
@@ -1558,8 +1562,17 @@ static int mmc_select_hs200(struct mmc_card *card)
false, true);
if (err)
goto err;
/*
* Bump to HS timing and frequency. Some cards don't handle
* SEND_STATUS reliably at the initial frequency.
* NB: We can't move to full (HS200) speeds until after we've
* successfully switched over.
*/
old_timing = host->ios.timing;
old_clock = host->ios.clock;
mmc_set_timing(host, MMC_TIMING_MMC_HS200);
mmc_set_clock(card->host, card->ext_csd.hs_max_dtr);
/*
* For HS200, CRC errors are not a reliable way to know the
@@ -1572,8 +1585,10 @@ static int mmc_select_hs200(struct mmc_card *card)
* mmc_select_timing() assumes timing has not changed if
* it is a switch error.
*/
if (err == -EBADMSG)
if (err == -EBADMSG) {
mmc_set_clock(host, old_clock);
mmc_set_timing(host, old_timing);
}
}
err:
if (err) {
@@ -1665,7 +1680,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
* respond.
* mmc_go_idle is needed for eMMC that are asleep
*/
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
mmc_go_idle(host);
#endif
@@ -1712,7 +1727,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
card->ocr = ocr;
card->type = MMC_TYPE_MMC;
card->rca = 1;
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
#endif
}
@@ -1745,7 +1760,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
err = mmc_decode_csd(card);
if (err)
goto free_card;
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
err = mmc_decode_cid(card);
if (err)
goto free_card;
@@ -1892,7 +1907,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
/*
* Enable HPI feature (if supported)
*/
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
if (card->ext_csd.hpi) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_HPI_MGMT, 1,

View File

@@ -145,7 +145,7 @@ int mmc_go_idle(struct mmc_host *host)
* rules that must accommodate non-MMC slaves which this layer
* won't even know about.
*/
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
if (!mmc_host_is_spi(host)) {
mmc_set_chip_select(host, MMC_CS_HIGH);
mmc_delay(1);
@@ -157,7 +157,7 @@ int mmc_go_idle(struct mmc_host *host)
err = mmc_wait_for_cmd(host, &cmd, 0);
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
mmc_delay(1);
if (!mmc_host_is_spi(host)) {
@@ -179,12 +179,12 @@ int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
cmd.arg = mmc_host_is_spi(host) ? 0 : ocr;
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR;
for (i = 100; i; i--) {
for (i = 1000; i; i--) {
err = mmc_wait_for_cmd(host, &cmd, 0);
if (err)
break;
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
/* if we're just probing, do a single pass */
if (ocr == 0)
break;
@@ -219,7 +219,7 @@ int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
*/
if (!ocr && !mmc_host_is_spi(host))
cmd.arg = cmd.resp[0] | BIT(30);
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
mmc_delay(1);
#else
udelay(1);

View File

@@ -3195,7 +3195,8 @@ static int __mmc_test_register_dbgfs_file(struct mmc_card *card,
struct mmc_test_dbgfs_file *df;
if (card->debugfs_root)
debugfs_create_file(name, mode, card->debugfs_root, card, fops);
file = debugfs_create_file(name, mode, card->debugfs_root,
card, fops);
df = kmalloc(sizeof(*df), GFP_KERNEL);
if (!df) {

View File

@@ -101,6 +101,12 @@ static const struct mmc_fixup __maybe_unused mmc_blk_fixups[] = {
MMC_FIXUP("V10016", CID_MANFID_KINGSTON, CID_OEMID_ANY, add_quirk_mmc,
MMC_QUIRK_TRIM_BROKEN),
/*
* Some SD cards reports discard support while they don't
*/
MMC_FIXUP(CID_NAME_ANY, CID_MANFID_SANDISK_SD, 0x5344, add_quirk_sd,
MMC_QUIRK_BROKEN_SD_DISCARD),
END_FIXUP
};

View File

@@ -857,7 +857,8 @@ try_again:
* 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 & 0x01000000)) {
if (!mmc_host_is_spi(host) && (ocr & SD_OCR_S18R) &&
rocr && (*rocr & SD_ROCR_S18A)) {
err = mmc_set_uhs_voltage(host, pocr);
if (err == -EAGAIN) {
retries--;
@@ -936,15 +937,16 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
/* Erase init depends on CSD and SSR */
mmc_init_erase(card);
/*
* Fetch switch information from card.
*/
err = mmc_read_switch(card);
if (err)
return err;
}
/*
* Fetch switch information from card. Note, sd3_bus_mode can change if
* voltage switch outcome changes, so do this always.
*/
err = mmc_read_switch(card);
if (err)
return err;
/*
* For SPI, enable CRC as appropriate.
* This CRC enable is located AFTER the reading of the
@@ -1093,26 +1095,15 @@ retry:
if (!v18_fixup_failed && !mmc_host_is_spi(host) && mmc_host_uhs(host) &&
mmc_sd_card_using_v18(card) &&
host->ios.signal_voltage != MMC_SIGNAL_VOLTAGE_180) {
/*
* Re-read switch information in case it has changed since
* oldcard was initialized.
*/
if (oldcard) {
err = mmc_read_switch(card);
if (err)
goto free_card;
}
if (mmc_sd_card_using_v18(card)) {
if (mmc_host_set_uhs_voltage(host) ||
mmc_sd_init_uhs_card(card)) {
v18_fixup_failed = true;
mmc_power_cycle(host, ocr);
if (!oldcard)
mmc_remove_card(card);
goto retry;
}
goto done;
if (mmc_host_set_uhs_voltage(host) ||
mmc_sd_init_uhs_card(card)) {
v18_fixup_failed = true;
mmc_power_cycle(host, ocr);
if (!oldcard)
mmc_remove_card(card);
goto retry;
}
goto cont;
}
/* Initialization sequence for UHS-I cards */
@@ -1147,7 +1138,7 @@ retry:
mmc_set_bus_width(host, MMC_BUS_WIDTH_4);
}
}
cont:
if (host->cqe_ops && !host->cqe_enabled) {
err = host->cqe_ops->cqe_enable(host, card);
if (!err) {
@@ -1165,7 +1156,7 @@ retry:
err = -EINVAL;
goto free_card;
}
done:
host->card = card;
return 0;

View File

@@ -126,7 +126,7 @@ int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
cmd.arg = ocr;
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R3 | MMC_CMD_BCR;
for (i = 100; i; i--) {
for (i = 200; i; i--) {
err = mmc_wait_for_app_cmd(host, NULL, &cmd);
if (err)
break;

View File

@@ -292,7 +292,8 @@ static void sdio_release_func(struct device *dev)
{
struct sdio_func *func = dev_to_sdio_func(dev);
sdio_free_func_cis(func);
if (!(func->card->quirks & MMC_QUIRK_NONSTD_SDIO))
sdio_free_func_cis(func);
kfree(func->info);
kfree(func->tmpbuf);

View File

@@ -1081,9 +1081,10 @@ config MMC_SDHCI_OMAP
config MMC_SDHCI_AM654
tristate "Support for the SDHCI Controller in TI's AM654 SOCs"
depends on MMC_SDHCI_PLTFM && OF && REGMAP_MMIO
depends on MMC_SDHCI_PLTFM && OF
select MMC_SDHCI_IO_ACCESSORS
select MMC_CQHCI
select REGMAP_MMIO
help
This selects the Secure Digital Host Controller Interface (SDHCI)
support present in TI's AM654 SOCs. The controller supports

View File

@@ -1097,8 +1097,9 @@ out5:
if (host->platdata && host->platdata->cd_setup &&
!(mmc->caps & MMC_CAP_NEEDS_POLL))
host->platdata->cd_setup(mmc, 0);
out_clk:
clk_disable_unprepare(host->clk);
out_clk:
clk_put(host->clk);
out_irq:
free_irq(host->irq, host);

View File

@@ -277,6 +277,7 @@ static int octeon_mmc_probe(struct platform_device *pdev)
if (ret) {
dev_err(&pdev->dev, "Error populating slots\n");
octeon_mmc_set_shared_power(host, 0);
of_node_put(cn);
goto error;
}
i++;

View File

@@ -142,8 +142,10 @@ static int thunder_mmc_probe(struct pci_dev *pdev,
continue;
ret = cvm_mmc_of_slot_probe(&host->slot_pdev[i]->dev, host);
if (ret)
if (ret) {
of_node_put(child_node);
goto error;
}
}
i++;
}

View File

@@ -124,6 +124,8 @@ void rv1106_sdmmc_put_lock(void)
EXPORT_SYMBOL(rv1106_sdmmc_put_lock);
#endif
#define RV1106_RAMDON_DATA_SIZE 508
#if defined(CONFIG_DEBUG_FS)
static int dw_mci_req_show(struct seq_file *s, void *v)
{
@@ -239,7 +241,7 @@ static void dw_mci_wait_while_busy(struct dw_mci *host, u32 cmd_flags)
* ...also allow sending for SDMMC_CMD_VOLT_SWITCH where busy is
* expected.
*/
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
if (host->slot->mmc->caps2 & MMC_CAP2_NO_SD &&
host->slot->mmc->caps2 & MMC_CAP2_NO_SDIO)
delay = 0;
@@ -525,8 +527,7 @@ static void dw_mci_dmac_complete_dma(void *arg)
tasklet_schedule(&host->tasklet);
}
if (host->need_xfer_timer &&
host->dir_status == DW_MCI_RECV_STATUS)
if (host->need_xfer_timer)
del_timer(&host->xfer_timer);
}
@@ -739,7 +740,7 @@ static inline int dw_mci_prepare_desc32(struct dw_mci *host,
if (host->is_rv1106_sd && (data->flags & MMC_DATA_WRITE)) {
desc->des0 = desc_last->des0;
desc->des2 = desc_last->des2;
desc->des1 = 0x8; /* Random dirty data for last one desc */
desc->des1 = RV1106_RAMDON_DATA_SIZE; /* Random dirty data for last one desc */
desc_last = desc;
}
@@ -1447,13 +1448,6 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
return;
}
if (host->is_rv1106_sd) {
u32 reg;
readl_poll_timeout(host->regs + SDMMC_STATUS, reg,
reg & BIT(2), USEC_PER_MSEC, 500 * USEC_PER_MSEC);
}
spin_lock_bh(&host->lock);
if (host->is_rv1106_sd)
@@ -1468,7 +1462,7 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct dw_mci_slot *slot = mmc_priv(mmc);
const struct dw_mci_drv_data *drv_data = slot->host->drv_data;
u32 regs;
u32 regs, power_off_delay;
int ret;
switch (ios->bus_width) {
@@ -1507,6 +1501,15 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
switch (ios->power_mode) {
case MMC_POWER_UP:
if (dw_mci_get_cd(mmc) && !IS_ERR_OR_NULL(slot->host->pinctrl)) {
if (!pinctrl_select_state(slot->host->pinctrl, slot->host->idle_state)) {
if (device_property_read_u32(slot->host->dev, "power-off-delay-ms",
&power_off_delay))
power_off_delay = 200;
msleep(power_off_delay);
}
}
if (!IS_ERR(mmc->supply.vmmc)) {
ret = mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
ios->vdd);
@@ -1523,6 +1526,9 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
mci_writel(slot->host, PWREN, regs);
break;
case MMC_POWER_ON:
if (!IS_ERR_OR_NULL(slot->host->pinctrl))
pinctrl_select_state(slot->host->pinctrl, slot->host->normal_state);
if (!slot->host->vqmmc_enabled) {
if (!IS_ERR(mmc->supply.vqmmc)) {
ret = regulator_enable(mmc->supply.vqmmc);
@@ -1537,9 +1543,11 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
slot->host->vqmmc_enabled = true;
}
#ifndef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
/* Reset our state machine after powering on */
dw_mci_ctrl_reset(slot->host,
SDMMC_CTRL_ALL_RESET_FLAGS);
#endif
}
/* Adjust clock / bus width after power is up */
@@ -1547,6 +1555,9 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
break;
case MMC_POWER_OFF:
if (!IS_ERR_OR_NULL(slot->host->pinctrl))
pinctrl_select_state(slot->host->pinctrl, slot->host->idle_state);
/* Turn clock off before power goes down */
dw_mci_setup_bus(slot, false);
@@ -1859,6 +1870,9 @@ static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
WARN_ON(host->cmd || host->data);
if (host->need_xfer_timer)
del_timer(&host->xfer_timer);
host->slot->mrq = NULL;
host->mrq = NULL;
if (!list_empty(&host->queue)) {
@@ -2004,8 +2018,10 @@ static void dw_mci_set_xfer_timeout(struct dw_mci *host)
host->bus_hz);
/* add a bit spare time */
xfer_ms += 100;
if (host->dir_status == DW_MCI_RECV_STATUS)
xfer_ms += 100;
else
xfer_ms += 2500;
spin_lock_irqsave(&host->irq_lock, irqflags);
if (!test_bit(EVENT_XFER_COMPLETE, &host->pending_events))
mod_timer(&host->xfer_timer,
@@ -2140,6 +2156,13 @@ static void dw_mci_tasklet_func(unsigned long priv)
send_stop_abort(host, data);
dw_mci_stop_dma(host);
state = STATE_DATA_ERROR;
if (host->dir_status == DW_MCI_SEND_STATUS) {
data->bytes_xfered = 0;
data->error = -ETIMEDOUT;
host->data = NULL;
dw_mci_request_end(host, mrq);
goto unlock;
}
break;
}
@@ -2151,8 +2174,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
*/
if (host->dir_status == DW_MCI_RECV_STATUS)
dw_mci_set_drto(host);
if (host->need_xfer_timer &&
host->dir_status == DW_MCI_RECV_STATUS)
if (host->need_xfer_timer)
dw_mci_set_xfer_timeout(host);
break;
}
@@ -2194,6 +2216,8 @@ static void dw_mci_tasklet_func(unsigned long priv)
*/
if (host->dir_status == DW_MCI_RECV_STATUS)
dw_mci_set_drto(host);
if (host->need_xfer_timer && host->dir_status == DW_MCI_SEND_STATUS)
dw_mci_set_xfer_timeout(host);
break;
}
@@ -2210,8 +2234,19 @@ static void dw_mci_tasklet_func(unsigned long priv)
}
/* stop command for open-ended transfer*/
if (data->stop)
if (data->stop) {
if (host->is_rv1106_sd && (data->flags & MMC_DATA_WRITE)) {
int fifo_count;
if (readl_poll_timeout_atomic(host->regs + SDMMC_STATUS, fifo_count,
((fifo_count >> 17) & 0x7FF) <= RV1106_RAMDON_DATA_SIZE / 4,
0, 5000 * USEC_PER_MSEC))
data->error = -ETIMEDOUT;
udelay(1);
dw_mci_reset(host);
}
send_stop_abort(host, data);
}
} else {
/*
* If we don't have a command complete now we'll
@@ -2742,8 +2777,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
del_timer(&host->cto_timer);
mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS);
host->cmd_status = pending;
if ((host->need_xfer_timer) &&
host->dir_status == DW_MCI_RECV_STATUS)
if (host->need_xfer_timer)
del_timer(&host->xfer_timer);
smp_wmb(); /* drain writebuffer */
set_bit(EVENT_CMD_COMPLETE, &host->pending_events);
@@ -3262,6 +3296,22 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
return ERR_PTR(ret);
}
host->pinctrl = devm_pinctrl_get(host->dev);
if (!IS_ERR(host->pinctrl)) {
host->normal_state = pinctrl_lookup_state(host->pinctrl, "normal");
if (IS_ERR(host->normal_state))
dev_warn(dev, "No normal pinctrl state\n");
host->idle_state = pinctrl_lookup_state(host->pinctrl, "idle");
if (IS_ERR(host->idle_state))
dev_warn(dev, "No idle pinctrl state\n");
if (!IS_ERR(host->normal_state) && !IS_ERR(host->idle_state))
pinctrl_select_state(host->pinctrl, host->idle_state);
else
host->pinctrl = NULL;
}
return pdata;
}
@@ -3317,7 +3367,7 @@ int dw_mci_probe(struct dw_mci *host)
}
}
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT
#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT_MMC
if (device_property_read_bool(host->dev, "no-sd") &&
device_property_read_bool(host->dev, "no-sdio")) {
if (readl_poll_timeout(host->regs + SDMMC_STATUS,

View File

@@ -233,6 +233,9 @@ struct dw_mci {
bool need_xfer_timer;
struct timer_list xfer_timer;
bool is_rv1106_sd;
struct pinctrl *pinctrl;
struct pinctrl_state *normal_state;
struct pinctrl_state *idle_state;
};
/* DMA ops for Internal/External DMAC interface */

View File

@@ -236,6 +236,26 @@ static int jz4740_mmc_acquire_dma_channels(struct jz4740_mmc_host *host)
return PTR_ERR(host->dma_rx);
}
/*
* Limit the maximum segment size in any SG entry according to
* the parameters of the DMA engine device.
*/
if (host->dma_tx) {
struct device *dev = host->dma_tx->device->dev;
unsigned int max_seg_size = dma_get_max_seg_size(dev);
if (max_seg_size < host->mmc->max_seg_size)
host->mmc->max_seg_size = max_seg_size;
}
if (host->dma_rx) {
struct device *dev = host->dma_rx->device->dev;
unsigned int max_seg_size = dma_get_max_seg_size(dev);
if (max_seg_size < host->mmc->max_seg_size)
host->mmc->max_seg_size = max_seg_size;
}
return 0;
}

View File

@@ -1161,8 +1161,10 @@ static int meson_mmc_probe(struct platform_device *pdev)
}
ret = device_reset_optional(&pdev->dev);
if (ret)
return dev_err_probe(&pdev->dev, ret, "device reset failed\n");
if (ret) {
dev_err_probe(&pdev->dev, ret, "device reset failed\n");
goto free_host;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
host->regs = devm_ioremap_resource(&pdev->dev, res);

View File

@@ -62,8 +62,8 @@ static int sdmmc_idma_validate_data(struct mmci_host *host,
* excepted the last element which has no constraint on idmasize
*/
for_each_sg(data->sg, sg, data->sg_len - 1, i) {
if (!IS_ALIGNED(data->sg->offset, sizeof(u32)) ||
!IS_ALIGNED(data->sg->length, SDMMC_IDMA_BURST)) {
if (!IS_ALIGNED(sg->offset, sizeof(u32)) ||
!IS_ALIGNED(sg->length, SDMMC_IDMA_BURST)) {
dev_err(mmc_dev(host->mmc),
"unaligned scatterlist: ofst:%x length:%d\n",
data->sg->offset, data->sg->length);
@@ -71,7 +71,7 @@ static int sdmmc_idma_validate_data(struct mmci_host *host,
}
}
if (!IS_ALIGNED(data->sg->offset, sizeof(u32))) {
if (!IS_ALIGNED(sg->offset, sizeof(u32))) {
dev_err(mmc_dev(host->mmc),
"unaligned last scatterlist: ofst:%x length:%d\n",
data->sg->offset, data->sg->length);

View File

@@ -111,8 +111,8 @@
#define CLK_DIV_MASK 0x7f
/* REG_BUS_WIDTH */
#define BUS_WIDTH_8 BIT(2)
#define BUS_WIDTH_4 BIT(1)
#define BUS_WIDTH_4_SUPPORT BIT(3)
#define BUS_WIDTH_4 BIT(2)
#define BUS_WIDTH_1 BIT(0)
#define MMC_VDD_360 23
@@ -527,9 +527,6 @@ static void moxart_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
case MMC_BUS_WIDTH_4:
writel(BUS_WIDTH_4, host->base + REG_BUS_WIDTH);
break;
case MMC_BUS_WIDTH_8:
writel(BUS_WIDTH_8, host->base + REG_BUS_WIDTH);
break;
default:
writel(BUS_WIDTH_1, host->base + REG_BUS_WIDTH);
break;
@@ -654,16 +651,8 @@ static int moxart_probe(struct platform_device *pdev)
dmaengine_slave_config(host->dma_chan_rx, &cfg);
}
switch ((readl(host->base + REG_BUS_WIDTH) >> 3) & 3) {
case 1:
if (readl(host->base + REG_BUS_WIDTH) & BUS_WIDTH_4_SUPPORT)
mmc->caps |= MMC_CAP_4_BIT_DATA;
break;
case 2:
mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
break;
default:
break;
}
writel(0, host->base + REG_INTERRUPT_MASK);

View File

@@ -2293,6 +2293,9 @@ static void msdc_cqe_disable(struct mmc_host *mmc, bool recovery)
/* disable busy check */
sdr_clr_bits(host->base + MSDC_PATCH_BIT1, MSDC_PB1_BUSY_CHECK_SEL);
val = readl(host->base + MSDC_INT);
writel(val, host->base + MSDC_INT);
if (recovery) {
sdr_set_field(host->base + MSDC_DMA_CTRL,
MSDC_DMA_CTRL_STOP, 1);
@@ -2693,11 +2696,14 @@ static int __maybe_unused msdc_suspend(struct device *dev)
{
struct mmc_host *mmc = dev_get_drvdata(dev);
int ret;
u32 val;
if (mmc->caps2 & MMC_CAP2_CQE) {
ret = cqhci_suspend(mmc);
if (ret)
return ret;
val = readl(((struct msdc_host *)mmc_priv(mmc))->base + MSDC_INT);
writel(val, ((struct msdc_host *)mmc_priv(mmc))->base + MSDC_INT);
}
return pm_runtime_force_suspend(dev);

View File

@@ -648,7 +648,7 @@ static int pxamci_probe(struct platform_device *pdev)
ret = pxamci_of_init(pdev, mmc);
if (ret)
return ret;
goto out;
host = mmc_priv(mmc);
host->mmc = mmc;
@@ -672,7 +672,7 @@ static int pxamci_probe(struct platform_device *pdev)
ret = pxamci_init_ocr(host);
if (ret < 0)
return ret;
goto out;
mmc->caps = 0;
host->cmdat = 0;

View File

@@ -390,10 +390,10 @@ static void renesas_sdhi_hs400_complete(struct mmc_host *mmc)
SH_MOBILE_SDHI_SCC_TMPPORT2_HS400OSEL) |
sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_TMPPORT2));
/* Set the sampling clock selection range of HS400 mode */
sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_DTCNTL,
SH_MOBILE_SDHI_SCC_DTCNTL_TAPEN |
0x4 << SH_MOBILE_SDHI_SCC_DTCNTL_TAPNUM_SHIFT);
sd_scc_read32(host, priv,
SH_MOBILE_SDHI_SCC_DTCNTL));
/* Avoid bad TAP */
if (bad_taps & BIT(priv->tap_set)) {

View File

@@ -37,10 +37,7 @@ struct realtek_pci_sdmmc {
bool double_clk;
bool eject;
bool initial_mode;
int power_state;
#define SDMMC_POWER_ON 1
#define SDMMC_POWER_OFF 0
int prev_power_state;
int sg_count;
s32 cookie;
int cookie_sg_count;
@@ -902,14 +899,21 @@ static int sd_set_bus_width(struct realtek_pci_sdmmc *host,
return err;
}
static int sd_power_on(struct realtek_pci_sdmmc *host)
static int sd_power_on(struct realtek_pci_sdmmc *host, unsigned char power_mode)
{
struct rtsx_pcr *pcr = host->pcr;
int err;
if (host->power_state == SDMMC_POWER_ON)
if (host->prev_power_state == MMC_POWER_ON)
return 0;
if (host->prev_power_state == MMC_POWER_UP) {
rtsx_pci_write_register(pcr, SD_BUS_STAT, SD_CLK_TOGGLE_EN, 0);
goto finish;
}
msleep(100);
rtsx_pci_init_cmd(pcr);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SELECT, 0x07, SD_MOD_SEL);
rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SHARE_MODE,
@@ -928,11 +932,17 @@ static int sd_power_on(struct realtek_pci_sdmmc *host)
if (err < 0)
return err;
mdelay(1);
err = rtsx_pci_write_register(pcr, CARD_OE, SD_OUTPUT_EN, SD_OUTPUT_EN);
if (err < 0)
return err;
host->power_state = SDMMC_POWER_ON;
/* send at least 74 clocks */
rtsx_pci_write_register(pcr, SD_BUS_STAT, SD_CLK_TOGGLE_EN, SD_CLK_TOGGLE_EN);
finish:
host->prev_power_state = power_mode;
return 0;
}
@@ -941,7 +951,7 @@ static int sd_power_off(struct realtek_pci_sdmmc *host)
struct rtsx_pcr *pcr = host->pcr;
int err;
host->power_state = SDMMC_POWER_OFF;
host->prev_power_state = MMC_POWER_OFF;
rtsx_pci_init_cmd(pcr);
@@ -967,7 +977,7 @@ static int sd_set_power_mode(struct realtek_pci_sdmmc *host,
if (power_mode == MMC_POWER_OFF)
err = sd_power_off(host);
else
err = sd_power_on(host);
err = sd_power_on(host, power_mode);
return err;
}
@@ -1404,10 +1414,11 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev)
host = mmc_priv(mmc);
host->pcr = pcr;
mmc->ios.power_delay_ms = 5;
host->mmc = mmc;
host->pdev = pdev;
host->cookie = -1;
host->power_state = SDMMC_POWER_OFF;
host->prev_power_state = MMC_POWER_OFF;
INIT_WORK(&host->work, sd_request);
platform_set_drvdata(pdev, host);
pcr->slots[RTSX_SD_CARD].p_dev = pdev;

View File

@@ -12,28 +12,55 @@
#include <linux/bitops.h>
#include <linux/delay.h>
#include "sdhci-cqhci.h"
#include "sdhci-pltfm.h"
#include "cqhci.h"
#define SDHCI_VENDOR 0x78
#define SDHCI_VENDOR_ENHANCED_STRB 0x1
#define SDHCI_VENDOR_GATE_SDCLK_EN 0x2
#define BRCMSTB_PRIV_FLAGS_NO_64BIT BIT(0)
#define BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT BIT(1)
#define BRCMSTB_MATCH_FLAGS_NO_64BIT BIT(0)
#define BRCMSTB_MATCH_FLAGS_BROKEN_TIMEOUT BIT(1)
#define BRCMSTB_MATCH_FLAGS_HAS_CLOCK_GATE BIT(2)
#define BRCMSTB_PRIV_FLAGS_HAS_CQE BIT(0)
#define BRCMSTB_PRIV_FLAGS_GATE_CLOCK BIT(1)
#define SDHCI_ARASAN_CQE_BASE_ADDR 0x200
struct sdhci_brcmstb_priv {
void __iomem *cfg_regs;
bool has_cqe;
unsigned int flags;
};
struct brcmstb_match_priv {
void (*hs400es)(struct mmc_host *mmc, struct mmc_ios *ios);
struct sdhci_ops *ops;
unsigned int flags;
const unsigned int flags;
};
static inline void enable_clock_gating(struct sdhci_host *host)
{
u32 reg;
reg = sdhci_readl(host, SDHCI_VENDOR);
reg |= SDHCI_VENDOR_GATE_SDCLK_EN;
sdhci_writel(host, reg, SDHCI_VENDOR);
}
void brcmstb_reset(struct sdhci_host *host, u8 mask)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_brcmstb_priv *priv = sdhci_pltfm_priv(pltfm_host);
sdhci_and_cqhci_reset(host, mask);
/* Reset will clear this, so re-enable it */
if (priv->flags & BRCMSTB_PRIV_FLAGS_GATE_CLOCK)
enable_clock_gating(host);
}
static void sdhci_brcmstb_hs400es(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct sdhci_host *host = mmc_priv(mmc);
@@ -129,22 +156,23 @@ static struct sdhci_ops sdhci_brcmstb_ops = {
static struct sdhci_ops sdhci_brcmstb_ops_7216 = {
.set_clock = sdhci_brcmstb_set_clock,
.set_bus_width = sdhci_set_bus_width,
.reset = sdhci_reset,
.reset = brcmstb_reset,
.set_uhs_signaling = sdhci_brcmstb_set_uhs_signaling,
};
static struct brcmstb_match_priv match_priv_7425 = {
.flags = BRCMSTB_PRIV_FLAGS_NO_64BIT |
BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT,
.flags = BRCMSTB_MATCH_FLAGS_NO_64BIT |
BRCMSTB_MATCH_FLAGS_BROKEN_TIMEOUT,
.ops = &sdhci_brcmstb_ops,
};
static struct brcmstb_match_priv match_priv_7445 = {
.flags = BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT,
.flags = BRCMSTB_MATCH_FLAGS_BROKEN_TIMEOUT,
.ops = &sdhci_brcmstb_ops,
};
static const struct brcmstb_match_priv match_priv_7216 = {
.flags = BRCMSTB_MATCH_FLAGS_HAS_CLOCK_GATE,
.hs400es = sdhci_brcmstb_hs400es,
.ops = &sdhci_brcmstb_ops_7216,
};
@@ -176,7 +204,7 @@ static int sdhci_brcmstb_add_host(struct sdhci_host *host,
bool dma64;
int ret;
if (!priv->has_cqe)
if ((priv->flags & BRCMSTB_PRIV_FLAGS_HAS_CQE) == 0)
return sdhci_add_host(host);
dev_dbg(mmc_dev(host->mmc), "CQE is enabled\n");
@@ -225,7 +253,6 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
struct sdhci_brcmstb_priv *priv;
struct sdhci_host *host;
struct resource *iomem;
bool has_cqe = false;
struct clk *clk;
int res;
@@ -244,10 +271,6 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
return res;
memset(&brcmstb_pdata, 0, sizeof(brcmstb_pdata));
if (device_property_read_bool(&pdev->dev, "supports-cqe")) {
has_cqe = true;
match_priv->ops->irq = sdhci_brcmstb_cqhci_irq;
}
brcmstb_pdata.ops = match_priv->ops;
host = sdhci_pltfm_init(pdev, &brcmstb_pdata,
sizeof(struct sdhci_brcmstb_priv));
@@ -258,7 +281,10 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
pltfm_host = sdhci_priv(host);
priv = sdhci_pltfm_priv(pltfm_host);
priv->has_cqe = has_cqe;
if (device_property_read_bool(&pdev->dev, "supports-cqe")) {
priv->flags |= BRCMSTB_PRIV_FLAGS_HAS_CQE;
match_priv->ops->irq = sdhci_brcmstb_cqhci_irq;
}
/* Map in the non-standard CFG registers */
iomem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
@@ -273,6 +299,14 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
if (res)
goto err;
/*
* Automatic clock gating does not work for SD cards that may
* voltage switch so only enable it for non-removable devices.
*/
if ((match_priv->flags & BRCMSTB_MATCH_FLAGS_HAS_CLOCK_GATE) &&
(host->mmc->caps & MMC_CAP_NONREMOVABLE))
priv->flags |= BRCMSTB_PRIV_FLAGS_GATE_CLOCK;
/*
* If the chip has enhanced strobe and it's enabled, add
* callback
@@ -287,14 +321,14 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
* properties through mmc_of_parse().
*/
host->caps = sdhci_readl(host, SDHCI_CAPABILITIES);
if (match_priv->flags & BRCMSTB_PRIV_FLAGS_NO_64BIT)
if (match_priv->flags & BRCMSTB_MATCH_FLAGS_NO_64BIT)
host->caps &= ~SDHCI_CAN_64BIT;
host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
host->caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_SDR104 |
SDHCI_SUPPORT_DDR50);
host->quirks |= SDHCI_QUIRK_MISSING_CAPS;
if (match_priv->flags & BRCMSTB_PRIV_FLAGS_BROKEN_TIMEOUT)
if (match_priv->flags & BRCMSTB_MATCH_FLAGS_BROKEN_TIMEOUT)
host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
res = sdhci_brcmstb_add_host(host, priv);

View File

@@ -0,0 +1,24 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright 2022 The Chromium OS Authors
*
* Support that applies to the combination of SDHCI and CQHCI, while not
* expressing a dependency between the two modules.
*/
#ifndef __MMC_HOST_SDHCI_CQHCI_H__
#define __MMC_HOST_SDHCI_CQHCI_H__
#include "cqhci.h"
#include "sdhci.h"
static inline void sdhci_and_cqhci_reset(struct sdhci_host *host, u8 mask)
{
if ((host->mmc->caps2 & MMC_CAP2_CQE) && (mask & SDHCI_RESET_ALL) &&
host->mmc->cqe_private)
cqhci_deactivate(host->mmc);
sdhci_reset(host, mask);
}
#endif /* __MMC_HOST_SDHCI_CQHCI_H__ */

View File

@@ -26,6 +26,7 @@
#include <linux/pinctrl/consumer.h>
#include <linux/platform_data/mmc-esdhc-imx.h>
#include <linux/pm_runtime.h>
#include "sdhci-cqhci.h"
#include "sdhci-pltfm.h"
#include "sdhci-esdhc.h"
#include "cqhci.h"
@@ -294,22 +295,6 @@ struct pltfm_imx_data {
struct pm_qos_request pm_qos_req;
};
static const struct platform_device_id imx_esdhc_devtype[] = {
{
.name = "sdhci-esdhc-imx25",
.driver_data = (kernel_ulong_t) &esdhc_imx25_data,
}, {
.name = "sdhci-esdhc-imx35",
.driver_data = (kernel_ulong_t) &esdhc_imx35_data,
}, {
.name = "sdhci-esdhc-imx51",
.driver_data = (kernel_ulong_t) &esdhc_imx51_data,
}, {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(platform, imx_esdhc_devtype);
static const struct of_device_id imx_esdhc_dt_ids[] = {
{ .compatible = "fsl,imx25-esdhc", .data = &esdhc_imx25_data, },
{ .compatible = "fsl,imx35-esdhc", .data = &esdhc_imx35_data, },
@@ -1243,7 +1228,7 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
static void esdhc_reset(struct sdhci_host *host, u8 mask)
{
sdhci_reset(host, mask);
sdhci_and_cqhci_reset(host, mask);
sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
@@ -1464,7 +1449,7 @@ static void esdhc_cqe_enable(struct mmc_host *mmc)
* system resume back.
*/
cqhci_writel(cq_host, 0, CQHCI_CTL);
if (cqhci_readl(cq_host, CQHCI_CTL) && CQHCI_HALT)
if (cqhci_readl(cq_host, CQHCI_CTL) & CQHCI_HALT)
dev_err(mmc_dev(host->mmc),
"failed to exit halt state when enable CQE\n");
@@ -1545,72 +1530,6 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
}
#endif
static int sdhci_esdhc_imx_probe_nondt(struct platform_device *pdev,
struct sdhci_host *host,
struct pltfm_imx_data *imx_data)
{
struct esdhc_platform_data *boarddata = &imx_data->boarddata;
int err;
if (!host->mmc->parent->platform_data) {
dev_err(mmc_dev(host->mmc), "no board data!\n");
return -EINVAL;
}
imx_data->boarddata = *((struct esdhc_platform_data *)
host->mmc->parent->platform_data);
/* write_protect */
if (boarddata->wp_type == ESDHC_WP_GPIO) {
host->mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
err = mmc_gpiod_request_ro(host->mmc, "wp", 0, 0);
if (err) {
dev_err(mmc_dev(host->mmc),
"failed to request write-protect gpio!\n");
return err;
}
}
/* card_detect */
switch (boarddata->cd_type) {
case ESDHC_CD_GPIO:
err = mmc_gpiod_request_cd(host->mmc, "cd", 0, false, 0);
if (err) {
dev_err(mmc_dev(host->mmc),
"failed to request card-detect gpio!\n");
return err;
}
fallthrough;
case ESDHC_CD_CONTROLLER:
/* we have a working card_detect back */
host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
break;
case ESDHC_CD_PERMANENT:
host->mmc->caps |= MMC_CAP_NONREMOVABLE;
break;
case ESDHC_CD_NONE:
break;
}
switch (boarddata->max_bus_width) {
case 8:
host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA;
break;
case 4:
host->mmc->caps |= MMC_CAP_4_BIT_DATA;
break;
case 1:
default:
host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
break;
}
return 0;
}
static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id =
@@ -1630,8 +1549,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
imx_data = sdhci_pltfm_priv(pltfm_host);
imx_data->socdata = of_id ? of_id->data : (struct esdhc_soc_data *)
pdev->id_entry->driver_data;
imx_data->socdata = of_id->data;
if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS)
cpu_latency_qos_add_request(&imx_data->pm_qos_req, 0);
@@ -1692,6 +1610,10 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
host->mmc_host_ops.execute_tuning = usdhc_execute_tuning;
}
err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data);
if (err)
goto disable_ahb_clk;
if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING)
sdhci_esdhc_ops.platform_execute_tuning =
esdhc_executing_tuning;
@@ -1699,13 +1621,15 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536)
host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
if (imx_data->socdata->flags & ESDHC_FLAG_HS400)
if (host->mmc->caps & MMC_CAP_8_BIT_DATA &&
imx_data->socdata->flags & ESDHC_FLAG_HS400)
host->quirks2 |= SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400;
if (imx_data->socdata->flags & ESDHC_FLAG_BROKEN_AUTO_CMD23)
host->quirks2 |= SDHCI_QUIRK2_ACMD23_BROKEN;
if (imx_data->socdata->flags & ESDHC_FLAG_HS400_ES) {
if (host->mmc->caps & MMC_CAP_8_BIT_DATA &&
imx_data->socdata->flags & ESDHC_FLAG_HS400_ES) {
host->mmc->caps2 |= MMC_CAP2_HS400_ES;
host->mmc_host_ops.hs400_enhanced_strobe =
esdhc_hs400_enhanced_strobe;
@@ -1727,13 +1651,6 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
goto disable_ahb_clk;
}
if (of_id)
err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data);
else
err = sdhci_esdhc_imx_probe_nondt(pdev, host, imx_data);
if (err)
goto disable_ahb_clk;
sdhci_esdhc_imx_hwinit(host);
err = sdhci_add_host(host);
@@ -1944,7 +1861,6 @@ static struct platform_driver sdhci_esdhc_imx_driver = {
.of_match_table = imx_esdhc_dt_ids,
.pm = &sdhci_esdhc_pmops,
},
.id_table = imx_esdhc_devtype,
.probe = sdhci_esdhc_imx_probe,
.remove = sdhci_esdhc_imx_remove,
};

View File

@@ -17,6 +17,7 @@
#include <linux/regulator/consumer.h>
#include <linux/interconnect.h>
#include <linux/pinctrl/consumer.h>
#include <linux/reset.h>
#include "sdhci-pltfm.h"
#include "cqhci.h"
@@ -2441,6 +2442,7 @@ static const struct sdhci_msm_variant_info sm8250_sdhci_var = {
static const struct of_device_id sdhci_msm_dt_match[] = {
{.compatible = "qcom,sdhci-msm-v4", .data = &sdhci_msm_mci_var},
{.compatible = "qcom,sdhci-msm-v5", .data = &sdhci_msm_v5_var},
{.compatible = "qcom,sdm670-sdhci", .data = &sdm845_sdhci_var},
{.compatible = "qcom,sdm845-sdhci", .data = &sdm845_sdhci_var},
{.compatible = "qcom,sm8250-sdhci", .data = &sm8250_sdhci_var},
{.compatible = "qcom,sc7180-sdhci", .data = &sdm845_sdhci_var},
@@ -2488,6 +2490,43 @@ static inline void sdhci_msm_get_of_property(struct platform_device *pdev,
of_property_read_u32(node, "qcom,dll-config", &msm_host->dll_config);
}
static int sdhci_msm_gcc_reset(struct device *dev, struct sdhci_host *host)
{
struct reset_control *reset;
int ret = 0;
reset = reset_control_get_optional_exclusive(dev, NULL);
if (IS_ERR(reset))
return dev_err_probe(dev, PTR_ERR(reset),
"unable to acquire core_reset\n");
if (!reset)
return ret;
ret = reset_control_assert(reset);
if (ret) {
reset_control_put(reset);
return dev_err_probe(dev, ret, "core_reset assert failed\n");
}
/*
* The hardware requirement for delay between assert/deassert
* is at least 3-4 sleep clock (32.7KHz) cycles, which comes to
* ~125us (4/32768). To be on the safe side add 200us delay.
*/
usleep_range(200, 210);
ret = reset_control_deassert(reset);
if (ret) {
reset_control_put(reset);
return dev_err_probe(dev, ret, "core_reset deassert failed\n");
}
usleep_range(200, 210);
reset_control_put(reset);
return ret;
}
static int sdhci_msm_probe(struct platform_device *pdev)
{
@@ -2536,6 +2575,10 @@ static int sdhci_msm_probe(struct platform_device *pdev)
msm_host->saved_tuning_phase = INVALID_TUNING_PHASE;
ret = sdhci_msm_gcc_reset(&pdev->dev, host);
if (ret)
goto pltfm_free;
/* Setup SDCC bus voter clock. */
msm_host->bus_clk = devm_clk_get(&pdev->dev, "bus");
if (!IS_ERR(msm_host->bus_clk)) {

View File

@@ -25,6 +25,7 @@
#include <linux/firmware/xlnx-zynqmp.h>
#include "cqhci.h"
#include "sdhci-cqhci.h"
#include "sdhci-pltfm.h"
#define SDHCI_ARASAN_VENDOR_REGISTER 0x78
@@ -359,7 +360,7 @@ static void sdhci_arasan_reset(struct sdhci_host *host, u8 mask)
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_arasan_data *sdhci_arasan = sdhci_pltfm_priv(pltfm_host);
sdhci_reset(host, mask);
sdhci_and_cqhci_reset(host, mask);
if (sdhci_arasan->quirks & SDHCI_ARASAN_QUIRK_FORCE_CDTEST) {
ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);

View File

@@ -100,8 +100,13 @@ static void sdhci_at91_set_clock(struct sdhci_host *host, unsigned int clock)
static void sdhci_at91_set_uhs_signaling(struct sdhci_host *host,
unsigned int timing)
{
if (timing == MMC_TIMING_MMC_DDR52)
sdhci_writeb(host, SDMMC_MC1R_DDR, SDMMC_MC1R);
u8 mc1r;
if (timing == MMC_TIMING_MMC_DDR52) {
mc1r = sdhci_readb(host, SDMMC_MC1R);
mc1r |= SDMMC_MC1R_DDR;
sdhci_writeb(host, mc1r, SDMMC_MC1R);
}
sdhci_set_uhs_signaling(host, timing);
}

View File

@@ -27,11 +27,15 @@
/* DWCMSHC specific Mode Select value */
#define DWCMSHC_CTRL_HS400 0x7
#define DWCMSHC_VER_ID 0x500
#define DWCMSHC_VER_TYPE 0x504
#define DWCMSHC_HOST_CTRL3 0x508
#define DWCMSHC_EMMC_CONTROL 0x52c
#define DWCMSHC_EMMC_ATCTRL 0x540
/* DWC IP vendor area 1 pointer */
#define DWCMSHC_P_VENDOR_AREA1 0xe8
#define DWCMSHC_AREA1_MASK GENMASK(11, 0)
/* Offset inside the vendor area 1 */
#define DWCMSHC_HOST_CTRL3 0x8
#define DWCMSHC_EMMC_CONTROL 0x2c
#define DWCMSHC_CARD_IS_EMMC BIT(0)
#define DWCMSHC_ENHANCED_STROBE BIT(8)
#define DWCMSHC_EMMC_ATCTRL 0x40
/* Rockchip specific Registers */
#define DWCMSHC_EMMC_DLL_CTRL 0x800
@@ -41,30 +45,30 @@
#define DECMSHC_EMMC_DLL_CMDOUT 0x810
#define DWCMSHC_EMMC_DLL_STATUS0 0x840
#define DWCMSHC_EMMC_DLL_STATUS1 0x844
#define DWCMSHC_EMMC_DLL_START BIT(0)
#define DWCMSHC_EMMC_DLL_LOCKED BIT(8)
#define DWCMSHC_EMMC_DLL_TIMEOUT BIT(9)
#define DWCMSHC_EMMC_DLL_RXCLK_SRCSEL 29
#define DWCMSHC_EMMC_DLL_START_POINT 16
#define DWCMSHC_EMMC_DLL_INC 8
#define DWCMSHC_EMMC_DLL_BYPASS BIT(24)
#define DWCMSHC_EMMC_DLL_DLYENA BIT(27)
#define DLL_TAP_VALUE_SEL BIT(25)
#define DLL_TAP_VALUE_OFFSET 8
#define DLL_TXCLK_TAPNUM_DEFAULT 0x10
#define DLL_TXCLK_TAPNUM_90_DEGREES 0xA
#define DLL_TXCLK_TAPNUM_FROM_SW BIT(24)
#define DLL_TXCLK_NO_INVERTER BIT(29)
#define DLL_STRBIN_TAPNUM_DEFAULT 0x8
#define DLL_STRBIN_TAPNUM_FROM_SW BIT(24)
#define DLL_STRBIN_DELAY_NUM_SEL BIT(26)
#define DLL_STRBIN_DELAY_NUM_OFFSET 16
#define DLL_STRBIN_DELAY_NUM_DEFAULT 0x16
#define DLL_RXCLK_NO_INVERTER 1
#define DLL_RXCLK_INVERTER 0
#define DLL_CMDOUT_TAPNUM_90_DEGREES 0x8
#define DLL_RXCLK_TAPNUM_FROM_SW BIT(24)
#define DLL_RXCLK_NO_INVERTER BIT(29)
#define DLL_RXCLK_ORI_GATE BIT(31)
#define DLL_RXCLK_MAX_TAP 32
#define DWCMSHC_CARD_IS_EMMC BIT(0)
#define DWCMSHC_ENHANCED_STROBE BIT(8)
#define DLL_CMDOUT_TAPNUM_FROM_SW BIT(24)
#define DLL_CMDOUT_SRC_CLK_NEG BIT(28)
#define DLL_CMDOUT_EN_SRC_CLK_NEG BIT(29)
@@ -73,18 +77,23 @@
#define DLL_LOCK_WO_TMOUT(x) \
((((x) & DWCMSHC_EMMC_DLL_LOCKED) == DWCMSHC_EMMC_DLL_LOCKED) && \
(((x) & DWCMSHC_EMMC_DLL_TIMEOUT) == 0))
#define ROCKCHIP_MAX_CLKS 3
#define RK35xx_MAX_CLKS 3
#define BOUNDARY_OK(addr, len) \
((addr | (SZ_128M - 1)) == ((addr + len - 1) | (SZ_128M - 1)))
enum dwcmshc_rk_type {
DWCMSHC_RK3568,
DWCMSHC_RK3588,
};
struct dwcmshc_driver_data {
const struct sdhci_pltfm_data *pdata;
u32 flags;
#define RK_PLATFROM BIT(0)
#define RK_DLL_CMD_OUT BIT(1)
#define RK_RXCLK_NO_INVERTER BIT(2)
#define RK_RXCLK_SW_TUNING BIT(3)
#define RK_TAP_VALUE_SEL BIT(3)
u8 hs200_tx_tap;
u8 hs400_tx_tap;
@@ -93,19 +102,24 @@ struct dwcmshc_driver_data {
u8 hs400_strbin_tap;
};
struct dwcmshc_priv {
struct clk *bus_clk;
u32 cclk_rate;
u8 hs200_rx_tap;
struct rk35xx_priv {
/* Rockchip specified optional clocks */
struct clk_bulk_data rockchip_clks[ROCKCHIP_MAX_CLKS];
struct clk_bulk_data rockchip_clks[RK35xx_MAX_CLKS];
struct reset_control *reset;
enum dwcmshc_rk_type devtype;
u8 txclk_tapnum;
u32 cclk_rate;
unsigned int actual_clk;
const struct dwcmshc_driver_data *drv_data;
u32 acpi_en;
};
struct dwcmshc_priv {
struct clk *bus_clk;
int vendor_specific_area1; /* P_VENDOR_SPECIFIC_AREA reg */
void *priv; /* pointer to SoC private stuff */
};
/*
* If DMA addr spans 128MB boundary, we split the DMA transfer into two
* so that each DMA transfer doesn't exceed the boundary.
@@ -129,6 +143,16 @@ static void dwcmshc_adma_write_desc(struct sdhci_host *host, void **desc,
sdhci_adma_write_desc(host, desc, addr, len, cmd);
}
static unsigned int dwcmshc_get_max_clock(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
if (pltfm_host->clk)
return sdhci_pltfm_clk_get_max_clock(host);
else
return pltfm_host->clock;
}
static void dwcmshc_check_auto_cmd23(struct mmc_host *mmc,
struct mmc_request *mrq)
{
@@ -155,7 +179,9 @@ static void dwcmshc_request(struct mmc_host *mmc, struct mmc_request *mrq)
static void dwcmshc_set_uhs_signaling(struct sdhci_host *host,
unsigned int timing)
{
u16 ctrl_2, ctrl;
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
u16 ctrl, ctrl_2;
ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
/* Select Bus Speed Mode for host */
@@ -175,9 +201,9 @@ static void dwcmshc_set_uhs_signaling(struct sdhci_host *host,
ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
else if (timing == MMC_TIMING_MMC_HS400) {
/* set CARD_IS_EMMC bit to enable Data Strobe for HS400 */
ctrl = sdhci_readw(host, DWCMSHC_EMMC_CONTROL);
ctrl = sdhci_readw(host, priv->vendor_specific_area1 + DWCMSHC_EMMC_CONTROL);
ctrl |= DWCMSHC_CARD_IS_EMMC;
sdhci_writew(host, ctrl, DWCMSHC_EMMC_CONTROL);
sdhci_writew(host, ctrl, priv->vendor_specific_area1 + DWCMSHC_EMMC_CONTROL);
ctrl_2 |= DWCMSHC_CTRL_HS400;
}
@@ -190,22 +216,27 @@ static void dwcmshc_hs400_enhanced_strobe(struct mmc_host *mmc,
{
u32 vendor;
struct sdhci_host *host = mmc_priv(mmc);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
int reg = priv->vendor_specific_area1 + DWCMSHC_EMMC_CONTROL;
vendor = sdhci_readl(host, DWCMSHC_EMMC_CONTROL);
vendor = sdhci_readl(host, reg);
if (ios->enhanced_strobe)
vendor |= DWCMSHC_ENHANCED_STROBE;
else
vendor &= ~DWCMSHC_ENHANCED_STROBE;
sdhci_writel(host, vendor, DWCMSHC_EMMC_CONTROL);
sdhci_writel(host, vendor, reg);
}
static void dwcmshc_rk_set_clock(struct sdhci_host *host, unsigned int clock)
static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
struct dwcmshc_priv *dwc_priv = sdhci_pltfm_priv(pltfm_host);
struct rk35xx_priv *priv = dwc_priv->priv;
const struct dwcmshc_driver_data *drv_data = priv->drv_data;
u32 txclk_tapnum, extra, rxclk_tapnum;
u8 txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT;
u32 extra, reg, dll_lock_value;
int err;
host->mmc->actual_clock = 0;
@@ -238,13 +269,19 @@ static void dwcmshc_rk_set_clock(struct sdhci_host *host, unsigned int clock)
sdhci_set_clock(host, clock);
/* Disable cmd conflict check */
extra = sdhci_readl(host, DWCMSHC_HOST_CTRL3);
reg = dwc_priv->vendor_specific_area1 + DWCMSHC_HOST_CTRL3;
extra = sdhci_readl(host, reg);
extra &= ~BIT(0);
sdhci_writel(host, extra, DWCMSHC_HOST_CTRL3);
sdhci_writel(host, extra, reg);
/* Disable output clock while config DLL */
sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
if (clock <= 52000000) {
/* Disable DLL */
sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL);
/*
* Disable DLL and reset both of sample and drive clock.
* Config DLL BYPASS and Reset both of sample and drive clock.
* The bypass bit and start bit need to set if DLL is not locked.
*/
sdhci_writel(host, DWCMSHC_EMMC_DLL_BYPASS | DWCMSHC_EMMC_DLL_START, DWCMSHC_EMMC_DLL_CTRL);
@@ -260,7 +297,7 @@ static void dwcmshc_rk_set_clock(struct sdhci_host *host, unsigned int clock)
DLL_STRBIN_DELAY_NUM_SEL |
drv_data->ddr50_strbin_delay_num << DLL_STRBIN_DELAY_NUM_OFFSET;
sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN);
return;
goto exit;
}
/* Reset DLL */
@@ -270,6 +307,7 @@ static void dwcmshc_rk_set_clock(struct sdhci_host *host, unsigned int clock)
/* Init DLL settings, clean start bit before resetting */
sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL);
/* Init DLL settings */
extra = 0x5 << DWCMSHC_EMMC_DLL_START_POINT |
0x2 << DWCMSHC_EMMC_DLL_INC |
DWCMSHC_EMMC_DLL_START;
@@ -279,26 +317,21 @@ static void dwcmshc_rk_set_clock(struct sdhci_host *host, unsigned int clock)
500 * USEC_PER_MSEC);
if (err) {
dev_err(mmc_dev(host->mmc), "DLL lock timeout!\n");
return;
goto exit;
}
dll_lock_value = ((sdhci_readl(host, DWCMSHC_EMMC_DLL_STATUS0) & 0xFF) * 2) & 0xFF;
extra = 0x1 << 16 | /* tune clock stop en */
0x3 << 17 | /* pre-change delay */
0x3 << 19; /* post-change delay */
sdhci_writel(host, extra, DWCMSHC_EMMC_ATCTRL);
sdhci_writel(host, extra, dwc_priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL);
rxclk_tapnum = priv->hs200_rx_tap;
if ((drv_data->flags & RK_RXCLK_NO_INVERTER) &&
host->mmc->ios.timing == MMC_TIMING_MMC_HS400) {
extra = drv_data->hs200_tx_tap - drv_data->hs400_tx_tap;
if (rxclk_tapnum + extra < DLL_RXCLK_MAX_TAP)
rxclk_tapnum += extra;
}
extra = DWCMSHC_EMMC_DLL_DLYENA | DLL_RXCLK_ORI_GATE;
if (drv_data->flags & RK_RXCLK_NO_INVERTER)
extra |= DLL_RXCLK_NO_INVERTER;
if (drv_data->flags & RK_RXCLK_SW_TUNING && priv->hs200_rx_tap)
extra |= DLL_RXCLK_TAPNUM_FROM_SW | rxclk_tapnum;
extra |= DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL;
if (drv_data->flags & RK_TAP_VALUE_SEL)
extra |= DLL_TAP_VALUE_SEL | dll_lock_value << DLL_TAP_VALUE_OFFSET;
sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK);
txclk_tapnum = drv_data->hs200_tx_tap;
@@ -310,33 +343,40 @@ static void dwcmshc_rk_set_clock(struct sdhci_host *host, unsigned int clock)
DWCMSHC_EMMC_DLL_DLYENA |
drv_data->hs400_cmd_tap |
DLL_CMDOUT_TAPNUM_FROM_SW;
if (drv_data->flags & RK_TAP_VALUE_SEL)
extra |= DLL_TAP_VALUE_SEL | dll_lock_value << DLL_TAP_VALUE_OFFSET;
sdhci_writel(host, extra, DECMSHC_EMMC_DLL_CMDOUT);
}
extra = DWCMSHC_EMMC_DLL_DLYENA |
DLL_TXCLK_TAPNUM_FROM_SW |
DLL_RXCLK_NO_INVERTER |
DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL |
txclk_tapnum;
if (drv_data->flags & RK_TAP_VALUE_SEL)
extra |= DLL_TAP_VALUE_SEL | dll_lock_value << DLL_TAP_VALUE_OFFSET;
sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK);
extra = DWCMSHC_EMMC_DLL_DLYENA |
drv_data->hs400_strbin_tap |
DLL_STRBIN_TAPNUM_FROM_SW;
if (drv_data->flags & RK_TAP_VALUE_SEL)
extra |= DLL_TAP_VALUE_SEL | dll_lock_value << DLL_TAP_VALUE_OFFSET;
sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN);
exit:
/* enable output clock */
sdhci_enable_clk(host, 0);
}
static void rockchip_sdhci_reset(struct sdhci_host *host, u8 mask)
static void rk35xx_sdhci_reset(struct sdhci_host *host, u8 mask)
{
struct sdhci_pltfm_host *pltfm_host;
struct dwcmshc_priv *priv;
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct dwcmshc_priv *dwc_priv = sdhci_pltfm_priv(pltfm_host);
struct rk35xx_priv *priv = dwc_priv->priv;
if (mask & SDHCI_RESET_ALL) {
pltfm_host = sdhci_priv(host);
priv = sdhci_pltfm_priv(pltfm_host);
if (!IS_ERR_OR_NULL(priv->reset)) {
reset_control_assert(priv->reset);
udelay(1);
reset_control_deassert(priv->reset);
}
if (mask & SDHCI_RESET_ALL && priv->reset) {
reset_control_assert(priv->reset);
udelay(1);
reset_control_deassert(priv->reset);
}
sdhci_reset(host, mask);
@@ -350,45 +390,21 @@ static void sdhci_dwcmshc_request_done(struct sdhci_host *host, struct mmc_reque
mmc_request_done(host->mmc, mrq);
}
static int dwcmshc_rk_execute_tuning(struct mmc_host *mmc, u32 opcode)
{
struct sdhci_host *host = mmc_priv(mmc);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
int rx_delay, dll_lock_num, ret;
u32 extra;
ret = sdhci_execute_tuning(mmc, opcode);
if (!ret) {
rx_delay = (sdhci_readl(host, DWCMSHC_EMMC_DLL_STATUS1) >> 8) & 0xFF;
dll_lock_num = sdhci_readl(host, DWCMSHC_EMMC_DLL_STATUS0) & 0xFF;
sdhci_reset_tuning(host);
priv->hs200_rx_tap = rx_delay * 16 / dll_lock_num;
extra = sdhci_readl(host, DWCMSHC_EMMC_DLL_RXCLK);
extra &= DLL_RXCLK_NO_INVERTER;
extra |= DWCMSHC_EMMC_DLL_DLYENA | DLL_RXCLK_ORI_GATE |
DLL_RXCLK_TAPNUM_FROM_SW | priv->hs200_rx_tap;
sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK);
}
return ret;
}
static const struct sdhci_ops sdhci_dwcmshc_ops = {
.set_clock = sdhci_set_clock,
.set_bus_width = sdhci_set_bus_width,
.set_uhs_signaling = dwcmshc_set_uhs_signaling,
.get_max_clock = sdhci_pltfm_clk_get_max_clock,
.get_max_clock = dwcmshc_get_max_clock,
.reset = sdhci_reset,
.adma_write_desc = dwcmshc_adma_write_desc,
};
static const struct sdhci_ops sdhci_dwcmshc_rk_ops = {
.set_clock = dwcmshc_rk_set_clock,
static const struct sdhci_ops sdhci_dwcmshc_rk35xx_ops = {
.set_clock = dwcmshc_rk3568_set_clock,
.set_bus_width = sdhci_set_bus_width,
.set_uhs_signaling = dwcmshc_set_uhs_signaling,
.get_max_clock = sdhci_pltfm_clk_get_max_clock,
.reset = rockchip_sdhci_reset,
.reset = rk35xx_sdhci_reset,
.adma_write_desc = dwcmshc_adma_write_desc,
.request_done = sdhci_dwcmshc_request_done,
};
@@ -399,20 +415,84 @@ static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = {
.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
};
static const struct sdhci_pltfm_data sdhci_dwcmshc_rk_pdata = {
.ops = &sdhci_dwcmshc_rk_ops,
#ifdef CONFIG_ACPI
static const struct sdhci_pltfm_data sdhci_dwcmshc_bf3_pdata = {
.ops = &sdhci_dwcmshc_ops,
.quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
SDHCI_QUIRK2_ACMD23_BROKEN,
};
#endif
static const struct sdhci_pltfm_data sdhci_dwcmshc_rk35xx_pdata = {
.ops = &sdhci_dwcmshc_rk35xx_ops,
.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN,
};
static int dwcmshc_rk35xx_init(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv)
{
int err;
struct rk35xx_priv *priv = dwc_priv->priv;
priv->reset = devm_reset_control_array_get_optional_exclusive(mmc_dev(host->mmc));
if (IS_ERR(priv->reset)) {
err = PTR_ERR(priv->reset);
dev_err(mmc_dev(host->mmc), "failed to get reset control %d\n", err);
return err;
}
priv->rockchip_clks[0].id = "axi";
priv->rockchip_clks[1].id = "block";
priv->rockchip_clks[2].id = "timer";
err = devm_clk_bulk_get_optional(mmc_dev(host->mmc), RK35xx_MAX_CLKS,
priv->rockchip_clks);
if (err) {
dev_err(mmc_dev(host->mmc), "failed to get clocks %d\n", err);
return err;
}
err = clk_bulk_prepare_enable(RK35xx_MAX_CLKS, priv->rockchip_clks);
if (err) {
dev_err(mmc_dev(host->mmc), "failed to enable clocks %d\n", err);
return err;
}
if (of_property_read_u8(mmc_dev(host->mmc)->of_node, "rockchip,txclk-tapnum",
&priv->txclk_tapnum))
priv->txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT;
/* Disable cmd conflict check */
sdhci_writel(host, 0x0, dwc_priv->vendor_specific_area1 + DWCMSHC_HOST_CTRL3);
/* Reset previous settings */
sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK);
sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_STRBIN);
return 0;
}
static void dwcmshc_rk35xx_postinit(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv)
{
/*
* Don't support highspeed bus mode with low clk speed as we
* cannot use DLL for this condition.
*/
if (host->mmc->f_max <= 52000000) {
dev_info(mmc_dev(host->mmc), "Disabling HS200/HS400, frequency too low (%d)\n",
host->mmc->f_max);
host->mmc->caps2 &= ~(MMC_CAP2_HS200 | MMC_CAP2_HS400);
host->mmc->caps &= ~(MMC_CAP_3_3V_DDR | MMC_CAP_1_8V_DDR);
}
}
static const struct dwcmshc_driver_data dwcmshc_drvdata = {
.pdata = &sdhci_dwcmshc_pdata,
.flags = 0,
};
static const struct dwcmshc_driver_data rk3568_drvdata = {
.pdata = &sdhci_dwcmshc_rk_pdata,
.pdata = &sdhci_dwcmshc_rk35xx_pdata,
.flags = RK_PLATFROM | RK_RXCLK_NO_INVERTER,
.hs200_tx_tap = 16,
.hs400_tx_tap = 8,
@@ -422,7 +502,7 @@ static const struct dwcmshc_driver_data rk3568_drvdata = {
};
static const struct dwcmshc_driver_data rk3588_drvdata = {
.pdata = &sdhci_dwcmshc_rk_pdata,
.pdata = &sdhci_dwcmshc_rk35xx_pdata,
.flags = RK_PLATFROM | RK_DLL_CMD_OUT,
.hs200_tx_tap = 16,
.hs400_tx_tap = 9,
@@ -432,8 +512,8 @@ static const struct dwcmshc_driver_data rk3588_drvdata = {
};
static const struct dwcmshc_driver_data rk3528_drvdata = {
.pdata = &sdhci_dwcmshc_rk_pdata,
.flags = RK_PLATFROM | RK_DLL_CMD_OUT | RK_RXCLK_SW_TUNING | RK_RXCLK_NO_INVERTER,
.pdata = &sdhci_dwcmshc_rk35xx_pdata,
.flags = RK_PLATFROM | RK_DLL_CMD_OUT | RK_TAP_VALUE_SEL,
.hs200_tx_tap = 12,
.hs400_tx_tap = 6,
.hs400_cmd_tap = 6,
@@ -441,51 +521,23 @@ static const struct dwcmshc_driver_data rk3528_drvdata = {
.ddr50_strbin_delay_num = 10,
};
static int rockchip_pltf_init(struct sdhci_host *host, struct dwcmshc_priv *priv)
{
int err;
priv->rockchip_clks[0].id = "axi";
priv->rockchip_clks[1].id = "block";
priv->rockchip_clks[2].id = "timer";
err = devm_clk_bulk_get_optional(mmc_dev(host->mmc), ROCKCHIP_MAX_CLKS,
priv->rockchip_clks);
if (err) {
dev_err(mmc_dev(host->mmc), "failed to get clocks %d\n", err);
return err;
}
err = clk_bulk_prepare_enable(ROCKCHIP_MAX_CLKS, priv->rockchip_clks);
if (err) {
dev_err(mmc_dev(host->mmc), "failed to enable clocks %d\n", err);
return err;
}
/* Disable cmd conflict check */
sdhci_writel(host, 0x0, DWCMSHC_HOST_CTRL3);
/* Reset previous settings */
sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK);
sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_STRBIN);
/*
* Don't support highspeed bus mode with low clk speed as we
* cannot use DLL for this condition.
*/
if (host->mmc->f_max <= 52000000) {
host->mmc->caps2 &= ~(MMC_CAP2_HS200 | MMC_CAP2_HS400);
host->mmc->caps &= ~(MMC_CAP_3_3V_DDR | MMC_CAP_1_8V_DDR);
}
return 0;
}
static const struct dwcmshc_driver_data rk3562_drvdata = {
.pdata = &sdhci_dwcmshc_rk35xx_pdata,
.flags = RK_PLATFROM | RK_DLL_CMD_OUT | RK_TAP_VALUE_SEL,
.hs200_tx_tap = 12,
.hs400_tx_tap = 6,
.hs400_cmd_tap = 6,
.hs400_strbin_tap = 3,
.ddr50_strbin_delay_num = 10,
};
static const struct of_device_id sdhci_dwcmshc_dt_ids[] = {
{
.compatible = "snps,dwcmshc-sdhci",
.data = &dwcmshc_drvdata,
.compatible = "rockchip,rk3588-dwcmshc",
.data = &rk3588_drvdata,
},
{
.compatible = "rockchip,dwcmshc-sdhci",
.compatible = "rockchip,rk3568-dwcmshc",
.data = &rk3568_drvdata,
},
{
@@ -493,17 +545,35 @@ static const struct of_device_id sdhci_dwcmshc_dt_ids[] = {
.data = &rk3528_drvdata,
},
{
.compatible = "rockchip,rk3588-dwcmshc",
.data = &rk3588_drvdata,
.compatible = "rockchip,rk3562-dwcmshc",
.data = &rk3562_drvdata,
},
{
.compatible = "snps,dwcmshc-sdhci",
.data = &dwcmshc_drvdata,
},
{},
};
MODULE_DEVICE_TABLE(of, sdhci_dwcmshc_dt_ids);
#ifdef CONFIG_ACPI
static const struct acpi_device_id sdhci_dwcmshc_acpi_ids[] = {
{
.id = "MLNXBF30",
.driver_data = (kernel_ulong_t)&sdhci_dwcmshc_bf3_pdata,
},
{}
};
#endif
static int dwcmshc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct sdhci_pltfm_host *pltfm_host;
struct sdhci_host *host;
struct dwcmshc_priv *priv;
struct rk35xx_priv *rk_priv = NULL;
const struct sdhci_pltfm_data *pltfm_data;
const struct dwcmshc_driver_data *drv_data;
struct mmc_hsq *hsq;
int err;
@@ -514,8 +584,9 @@ static int dwcmshc_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Error: No device match data found\n");
return -ENODEV;
}
pltfm_data = drv_data->pdata;
host = sdhci_pltfm_init(pdev, drv_data->pdata,
host = sdhci_pltfm_init(pdev, pltfm_data,
sizeof(struct dwcmshc_priv));
if (IS_ERR(host))
return PTR_ERR(host);
@@ -523,30 +594,26 @@ static int dwcmshc_probe(struct platform_device *pdev)
/*
* extra adma table cnt for cross 128M boundary handling.
*/
extra = DIV_ROUND_UP_ULL(dma_get_required_mask(&pdev->dev), SZ_128M);
extra = DIV_ROUND_UP_ULL(dma_get_required_mask(dev), SZ_128M);
if (extra > SDHCI_MAX_SEGS)
extra = SDHCI_MAX_SEGS;
host->adma_table_cnt += extra;
pltfm_host = sdhci_priv(host);
priv = sdhci_pltfm_priv(pltfm_host);
priv->drv_data = drv_data;
priv->acpi_en = has_acpi_companion(&pdev->dev);
if (!priv->acpi_en) {
priv->reset = devm_reset_control_array_get_exclusive(&pdev->dev);
pltfm_host->clk = devm_clk_get(&pdev->dev, "core");
if (dev->of_node) {
pltfm_host->clk = devm_clk_get(dev, "core");
if (IS_ERR(pltfm_host->clk)) {
err = PTR_ERR(pltfm_host->clk);
dev_err(&pdev->dev, "failed to get core clk: %d\n", err);
dev_err(dev, "failed to get core clk: %d\n", err);
goto free_pltfm;
}
err = clk_prepare_enable(pltfm_host->clk);
if (err)
goto free_pltfm;
priv->bus_clk = devm_clk_get(&pdev->dev, "bus");
priv->bus_clk = devm_clk_get(dev, "bus");
if (!IS_ERR(priv->bus_clk))
clk_prepare_enable(priv->bus_clk);
}
@@ -557,6 +624,9 @@ static int dwcmshc_probe(struct platform_device *pdev)
sdhci_get_of_property(pdev);
priv->vendor_specific_area1 =
sdhci_readl(host, DWCMSHC_P_VENDOR_AREA1) & DWCMSHC_AREA1_MASK;
host->mmc_host_ops.request = dwcmshc_request;
host->mmc_host_ops.hs400_enhanced_strobe = dwcmshc_hs400_enhanced_strobe;
@@ -570,20 +640,42 @@ static int dwcmshc_probe(struct platform_device *pdev)
if (err)
goto err_clk;
err = sdhci_add_host(host);
if (err)
goto err_clk;
if (drv_data->flags & RK_PLATFROM) {
priv->hs200_rx_tap = 0;
if (drv_data->flags & RK_RXCLK_SW_TUNING)
host->mmc_host_ops.execute_tuning = dwcmshc_rk_execute_tuning;
err = rockchip_pltf_init(host, priv);
rk_priv = devm_kzalloc(&pdev->dev, sizeof(struct rk35xx_priv), GFP_KERNEL);
if (!rk_priv) {
err = -ENOMEM;
goto err_clk;
}
rk_priv->drv_data = drv_data;
rk_priv->acpi_en = has_acpi_companion(&pdev->dev);
if (of_device_is_compatible(pdev->dev.of_node, "rockchip,rk3588-dwcmshc"))
rk_priv->devtype = DWCMSHC_RK3588;
else
rk_priv->devtype = DWCMSHC_RK3568;
priv->priv = rk_priv;
err = dwcmshc_rk35xx_init(host, priv);
if (err)
goto err_clk;
}
if (!priv->acpi_en) {
host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
err = sdhci_setup_host(host);
if (err)
goto err_clk;
if (rk_priv)
dwcmshc_rk35xx_postinit(host, priv);
err = __sdhci_add_host(host);
if (err)
goto err_setup_host;
if (rk_priv && !rk_priv->acpi_en) {
pm_runtime_get_noresume(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
@@ -594,10 +686,14 @@ static int dwcmshc_probe(struct platform_device *pdev)
return 0;
err_setup_host:
sdhci_cleanup_host(host);
err_clk:
clk_disable_unprepare(pltfm_host->clk);
clk_disable_unprepare(priv->bus_clk);
clk_bulk_disable_unprepare(ROCKCHIP_MAX_CLKS, priv->rockchip_clks);
if (rk_priv)
clk_bulk_disable_unprepare(RK35xx_MAX_CLKS,
rk_priv->rockchip_clks);
free_pltfm:
sdhci_pltfm_free(pdev);
return err;
@@ -608,13 +704,15 @@ static int dwcmshc_remove(struct platform_device *pdev)
struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
struct rk35xx_priv *rk_priv = priv->priv;
sdhci_remove_host(host, 0);
clk_disable_unprepare(pltfm_host->clk);
clk_disable_unprepare(priv->bus_clk);
clk_bulk_disable_unprepare(ROCKCHIP_MAX_CLKS, priv->rockchip_clks);
if (rk_priv)
clk_bulk_disable_unprepare(RK35xx_MAX_CLKS,
rk_priv->rockchip_clks);
sdhci_pltfm_free(pdev);
return 0;
@@ -626,6 +724,7 @@ static int dwcmshc_suspend(struct device *dev)
struct sdhci_host *host = dev_get_drvdata(dev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
struct rk35xx_priv *rk_priv = priv->priv;
int ret;
mmc_hsq_suspend(host->mmc);
@@ -638,7 +737,10 @@ static int dwcmshc_suspend(struct device *dev)
if (!IS_ERR(priv->bus_clk))
clk_disable_unprepare(priv->bus_clk);
clk_bulk_disable_unprepare(ROCKCHIP_MAX_CLKS, priv->rockchip_clks);
if (rk_priv)
clk_bulk_disable_unprepare(RK35xx_MAX_CLKS,
rk_priv->rockchip_clks);
return ret;
}
@@ -647,6 +749,7 @@ static int dwcmshc_resume(struct device *dev)
struct sdhci_host *host = dev_get_drvdata(dev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
struct rk35xx_priv *rk_priv = priv->priv;
int ret;
ret = clk_prepare_enable(pltfm_host->clk);
@@ -659,9 +762,12 @@ static int dwcmshc_resume(struct device *dev)
return ret;
}
ret = clk_bulk_prepare_enable(ROCKCHIP_MAX_CLKS, priv->rockchip_clks);
if (ret)
return ret;
if (rk_priv) {
ret = clk_bulk_prepare_enable(RK35xx_MAX_CLKS,
rk_priv->rockchip_clks);
if (ret)
return ret;
}
ret = sdhci_resume_host(host);
if (ret)
@@ -699,13 +805,13 @@ static const struct dev_pm_ops dwcmshc_pmops = {
SET_SYSTEM_SLEEP_PM_OPS(dwcmshc_suspend, dwcmshc_resume)
SET_RUNTIME_PM_OPS(dwcmshc_runtime_suspend, dwcmshc_runtime_resume, NULL)
};
MODULE_DEVICE_TABLE(of, sdhci_dwcmshc_dt_ids);
static struct platform_driver sdhci_dwcmshc_driver = {
.driver = {
.name = "sdhci-dwcmshc",
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = sdhci_dwcmshc_dt_ids,
.acpi_match_table = ACPI_PTR(sdhci_dwcmshc_acpi_ids),
.pm = &dwcmshc_pmops,
},
.probe = dwcmshc_probe,

View File

@@ -904,6 +904,7 @@ static int esdhc_signal_voltage_switch(struct mmc_host *mmc,
scfg_node = of_find_matching_node(NULL, scfg_device_ids);
if (scfg_node)
scfg_base = of_iomap(scfg_node, 0);
of_node_put(scfg_node);
if (scfg_base) {
sdhciovselcr = SDHCIOVSELCR_TGLEN |
SDHCIOVSELCR_VSELVAL;

View File

@@ -967,6 +967,12 @@ static bool glk_broken_cqhci(struct sdhci_pci_slot *slot)
dmi_match(DMI_SYS_VENDOR, "IRBIS"));
}
static bool jsl_broken_hs400es(struct sdhci_pci_slot *slot)
{
return slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_JSL_EMMC &&
dmi_match(DMI_BIOS_VENDOR, "ASUSTeK COMPUTER INC.");
}
static int glk_emmc_probe_slot(struct sdhci_pci_slot *slot)
{
int ret = byt_emmc_probe_slot(slot);
@@ -975,9 +981,11 @@ static int glk_emmc_probe_slot(struct sdhci_pci_slot *slot)
slot->host->mmc->caps2 |= MMC_CAP2_CQE;
if (slot->chip->pdev->device != PCI_DEVICE_ID_INTEL_GLK_EMMC) {
slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES,
slot->host->mmc_host_ops.hs400_enhanced_strobe =
intel_hs400_enhanced_strobe;
if (!jsl_broken_hs400es(slot)) {
slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES;
slot->host->mmc_host_ops.hs400_enhanced_strobe =
intel_hs400_enhanced_strobe;
}
slot->host->mmc->caps2 |= MMC_CAP2_CQE_DCMD;
}
@@ -1791,6 +1799,8 @@ static int amd_probe(struct sdhci_pci_chip *chip)
}
}
pci_dev_put(smbus_dev);
if (gen == AMD_CHIPSET_BEFORE_ML || gen == AMD_CHIPSET_CZ)
chip->quirks2 |= SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD;

View File

@@ -31,6 +31,7 @@
#define O2_SD_CAPS 0xE0
#define O2_SD_ADMA1 0xE2
#define O2_SD_ADMA2 0xE7
#define O2_SD_MISC_CTRL2 0xF0
#define O2_SD_INF_MOD 0xF1
#define O2_SD_MISC_CTRL4 0xFC
#define O2_SD_MISC_CTRL 0x1C0
@@ -147,6 +148,8 @@ static int sdhci_o2_get_cd(struct mmc_host *mmc)
if (!(sdhci_readw(host, O2_PLL_DLL_WDT_CONTROL1) & O2_PLL_LOCK_STATUS))
sdhci_o2_enable_internal_clock(host);
else
sdhci_o2_wait_card_detect_stable(host);
return !!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT);
}
@@ -820,6 +823,12 @@ static int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip)
/* Set Tuning Windows to 5 */
pci_write_config_byte(chip->pdev,
O2_SD_TUNING_CTRL, 0x55);
//Adjust 1st and 2nd CD debounce time
pci_read_config_dword(chip->pdev, O2_SD_MISC_CTRL2, &scratch_32);
scratch_32 &= 0xFFE7FFFF;
scratch_32 |= 0x00180000;
pci_write_config_dword(chip->pdev, O2_SD_MISC_CTRL2, scratch_32);
pci_write_config_dword(chip->pdev, O2_SD_DETECT_SETTING, 1);
/* Lock WP */
ret = pci_read_config_byte(chip->pdev,
O2_SD_LOCK_WP, &scratch);

View File

@@ -296,7 +296,7 @@ static unsigned int sdhci_sprd_get_max_clock(struct sdhci_host *host)
static unsigned int sdhci_sprd_get_min_clock(struct sdhci_host *host)
{
return 400000;
return 100000;
}
static void sdhci_sprd_set_uhs_signaling(struct sdhci_host *host,
@@ -457,7 +457,7 @@ static int sdhci_sprd_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios)
}
if (IS_ERR(sprd_host->pinctrl))
return 0;
goto reset;
switch (ios->signal_voltage) {
case MMC_SIGNAL_VOLTAGE_180:
@@ -485,6 +485,8 @@ static int sdhci_sprd_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios)
/* Wait for 300 ~ 500 us for pin state stable */
usleep_range(300, 500);
reset:
sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
return 0;

View File

@@ -24,6 +24,7 @@
#include <linux/gpio/consumer.h>
#include <linux/ktime.h>
#include "sdhci-cqhci.h"
#include "sdhci-pltfm.h"
#include "cqhci.h"
@@ -361,7 +362,7 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
u32 misc_ctrl, clk_ctrl, pad_ctrl;
sdhci_reset(host, mask);
sdhci_and_cqhci_reset(host, mask);
if (!(mask & SDHCI_RESET_ALL))
return;
@@ -760,7 +761,7 @@ static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
*/
host_clk = tegra_host->ddr_signaling ? clock * 2 : clock;
clk_set_rate(pltfm_host->clk, host_clk);
tegra_host->curr_clk_rate = host_clk;
tegra_host->curr_clk_rate = clk_get_rate(pltfm_host->clk);
if (tegra_host->ddr_signaling)
host->max_clk = host_clk;
else

View File

@@ -240,16 +240,6 @@ static void xenon_voltage_switch(struct sdhci_host *host)
{
/* Wait for 5ms after set 1.8V signal enable bit */
usleep_range(5000, 5500);
/*
* For some reason the controller's Host Control2 register reports
* the bit representing 1.8V signaling as 0 when read after it was
* written as 1. Subsequent read reports 1.
*
* Since this may cause some issues, do an empty read of the Host
* Control2 register here to circumvent this.
*/
sdhci_readw(host, SDHCI_HOST_CONTROL2);
}
static const struct sdhci_ops sdhci_xenon_ops = {

View File

@@ -15,6 +15,7 @@
#include <linux/sys_soc.h>
#include "cqhci.h"
#include "sdhci-cqhci.h"
#include "sdhci-pltfm.h"
/* CTL_CFG Registers */
@@ -147,6 +148,9 @@ struct sdhci_am654_data {
int drv_strength;
int strb_sel;
u32 flags;
u32 quirks;
#define SDHCI_AM654_QUIRK_FORCE_CDTEST BIT(0)
};
struct sdhci_am654_driver_data {
@@ -369,6 +373,21 @@ static void sdhci_am654_write_b(struct sdhci_host *host, u8 val, int reg)
}
}
static void sdhci_am654_reset(struct sdhci_host *host, u8 mask)
{
u8 ctrl;
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host);
sdhci_and_cqhci_reset(host, mask);
if (sdhci_am654->quirks & SDHCI_AM654_QUIRK_FORCE_CDTEST) {
ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
ctrl |= SDHCI_CTRL_CDTEST_INS | SDHCI_CTRL_CDTEST_EN;
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
}
}
static int sdhci_am654_execute_tuning(struct mmc_host *mmc, u32 opcode)
{
struct sdhci_host *host = mmc_priv(mmc);
@@ -446,7 +465,7 @@ static struct sdhci_ops sdhci_am654_ops = {
.set_clock = sdhci_am654_set_clock,
.write_b = sdhci_am654_write_b,
.irq = sdhci_am654_cqhci_irq,
.reset = sdhci_reset,
.reset = sdhci_and_cqhci_reset,
};
static const struct sdhci_pltfm_data sdhci_am654_pdata = {
@@ -476,7 +495,7 @@ static struct sdhci_ops sdhci_j721e_8bit_ops = {
.set_clock = sdhci_am654_set_clock,
.write_b = sdhci_am654_write_b,
.irq = sdhci_am654_cqhci_irq,
.reset = sdhci_reset,
.reset = sdhci_and_cqhci_reset,
};
static const struct sdhci_pltfm_data sdhci_j721e_8bit_pdata = {
@@ -500,7 +519,7 @@ static struct sdhci_ops sdhci_j721e_4bit_ops = {
.set_clock = sdhci_j721e_4bit_set_clock,
.write_b = sdhci_am654_write_b,
.irq = sdhci_am654_cqhci_irq,
.reset = sdhci_reset,
.reset = sdhci_am654_reset,
};
static const struct sdhci_pltfm_data sdhci_j721e_4bit_pdata = {
@@ -719,6 +738,9 @@ static int sdhci_am654_get_of_property(struct platform_device *pdev,
device_property_read_u32(dev, "ti,clkbuf-sel",
&sdhci_am654->clkbuf_sel);
if (device_property_read_bool(dev, "ti,fails-without-test-cd"))
sdhci_am654->quirks |= SDHCI_AM654_QUIRK_FORCE_CDTEST;
sdhci_get_of_property(pdev);
return 0;

View File

@@ -849,7 +849,7 @@ static int wmt_mci_probe(struct platform_device *pdev)
if (IS_ERR(priv->clk_sdmmc)) {
dev_err(&pdev->dev, "Error getting clock\n");
ret = PTR_ERR(priv->clk_sdmmc);
goto fail5;
goto fail5_and_a_half;
}
ret = clk_prepare_enable(priv->clk_sdmmc);
@@ -866,6 +866,9 @@ static int wmt_mci_probe(struct platform_device *pdev)
return 0;
fail6:
clk_put(priv->clk_sdmmc);
fail5_and_a_half:
dma_free_coherent(&pdev->dev, mmc->max_blk_count * 16,
priv->dma_desc_buffer, priv->dma_desc_device_addr);
fail5:
free_irq(dma_irq, priv);
fail4: