Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e11d06a5 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "mmc: Port changes for supporting SDIO functionality to 4.19 kernel"

parents 12c8d248 b01d47ac
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -380,6 +380,13 @@ int mmc_add_card(struct mmc_card *card)
#endif
	card->dev.of_node = mmc_of_find_child_device(card->host, 0);

	if (mmc_card_sdio(card)) {
		ret = device_init_wakeup(&card->dev, true);
		if (ret)
			pr_err("%s: %s: failed to init wakeup: %d\n",
				mmc_hostname(card->host), __func__, ret);
	}

	device_enable_async_suspend(&card->dev);

	ret = device_add(&card->dev);
+28 −0
Original line number Diff line number Diff line
@@ -182,6 +182,34 @@ int mmc_retune(struct mmc_host *host)
	return err;
}

/**
 *	mmc_host_may_gate_card - check if this card may be gated
 *	@card: card to check.
 */
bool mmc_host_may_gate_card(struct mmc_card *card)
{
	/* If there is no card we may gate it */
	if (!card)
		return true;

	/*
	 * SDIO3.0 card allows the clock to be gated off so check if
	 * that is the case or not
	 */
	if (mmc_card_sdio(card) && card->cccr.async_intr_sup)
		return true;

	/*
	 * Don't gate SDIO cards! These need to be clocked at all times
	 * since they may be independent systems generating interrupts
	 * and other events. The clock requests counter from the core will
	 * go down to zero since the core does not need it, but we will not
	 * gate the clock, because there is somebody out there that may still
	 * be using it.
	 */
	return !(card->quirks & MMC_QUIRK_BROKEN_CLK_GATING);
}

static void mmc_retune_timer(struct timer_list *t)
{
	struct mmc_host *host = from_timer(host, t, retune_timer);
+23 −0
Original line number Diff line number Diff line
@@ -153,6 +153,21 @@ static const struct mmc_fixup sdio_fixup_methods[] = {
	SDIO_FIXUP(SDIO_VENDOR_ID_TI_WL1251, SDIO_DEVICE_ID_TI_WL1251,
		   add_quirk, MMC_QUIRK_DISABLE_CD),

	SDIO_FIXUP(SDIO_VENDOR_ID_MSM_QCA, SDIO_DEVICE_ID_MSM_QCA_AR6003_1,
		   remove_quirk, MMC_QUIRK_BROKEN_CLK_GATING),

	SDIO_FIXUP(SDIO_VENDOR_ID_MSM_QCA, SDIO_DEVICE_ID_MSM_QCA_AR6003_2,
		   remove_quirk, MMC_QUIRK_BROKEN_CLK_GATING),

	SDIO_FIXUP(SDIO_VENDOR_ID_MSM_QCA, SDIO_DEVICE_ID_MSM_QCA_AR6004_1,
		   remove_quirk, MMC_QUIRK_BROKEN_CLK_GATING),

	SDIO_FIXUP(SDIO_VENDOR_ID_MSM_QCA, SDIO_DEVICE_ID_MSM_QCA_AR6004_2,
		   remove_quirk, MMC_QUIRK_BROKEN_CLK_GATING),

	SDIO_FIXUP(SDIO_VENDOR_ID_MSM, SDIO_DEVICE_ID_MSM_WCN1314,
		   remove_quirk, MMC_QUIRK_BROKEN_CLK_GATING),

	SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271,
		   add_quirk, MMC_QUIRK_NONSTD_FUNC_IF),

@@ -168,6 +183,14 @@ static const struct mmc_fixup sdio_fixup_methods[] = {
	SDIO_FIXUP(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8887WLAN,
		   add_limit_rate_quirk, 150000000),

	SDIO_FIXUP(SDIO_VENDOR_ID_QCA6574, SDIO_DEVICE_ID_QCA6574,
		   add_quirk, MMC_QUIRK_QCA6574_SETTINGS),

	SDIO_FIXUP(SDIO_VENDOR_ID_QCA9377, SDIO_DEVICE_ID_QCA9377,
		add_quirk, MMC_QUIRK_QCA9377_SETTINGS),

	SDIO_FIXUP(SDIO_VENDOR_ID_QCA9379, SDIO_DEVICE_ID_QCA9379,
		add_quirk, MMC_QUIRK_QCA9379_SETTINGS),
	END_FIXUP
};

+91 −6
Original line number Diff line number Diff line
@@ -184,6 +184,23 @@ static int sdio_read_cccr(struct mmc_card *card, u32 ocr)
				card->sw_caps.sd3_drv_type |= SD_DRIVER_TYPE_C;
			if (data & SDIO_DRIVE_SDTD)
				card->sw_caps.sd3_drv_type |= SD_DRIVER_TYPE_D;

			ret = mmc_io_rw_direct(card, 0, 0,
				SDIO_CCCR_INTERRUPT_EXTENSION, 0, &data);
			if (ret)
				goto out;
			if (data & SDIO_SUPPORT_ASYNC_INTR) {
				if (card->host->caps2 &
					MMC_CAP2_ASYNC_SDIO_IRQ_4BIT_MODE) {
					data |= SDIO_ENABLE_ASYNC_INTR;
					ret = mmc_io_rw_direct(card, 1, 0,
						SDIO_CCCR_INTERRUPT_EXTENSION,
						data, NULL);
					if (ret)
						goto out;
					card->cccr.async_intr_sup = 1;
				}
			}
		}

		/* if no uhs mode ensure we check for high speed */
@@ -202,12 +219,61 @@ static int sdio_read_cccr(struct mmc_card *card, u32 ocr)
	return ret;
}

static void sdio_enable_vendor_specific_settings(struct mmc_card *card)
{
	int ret;
	u8 settings;

	if (mmc_enable_qca6574_settings(card) ||
		mmc_enable_qca9377_settings(card) ||
		mmc_enable_qca9379_settings(card)) {
		ret = mmc_io_rw_direct(card, 1, 0, 0xF2, 0x0F, NULL);
		if (ret) {
			pr_crit("%s: failed to write to fn 0xf2 %d\n",
					mmc_hostname(card->host), ret);
			goto out;
		}

		ret = mmc_io_rw_direct(card, 0, 0, 0xF1, 0, &settings);
		if (ret) {
			pr_crit("%s: failed to read fn 0xf1 %d\n",
			mmc_hostname(card->host), ret);
			goto out;
		}

		settings |= 0x80;
		ret = mmc_io_rw_direct(card, 1, 0, 0xF1, settings, NULL);
		if (ret) {
			pr_crit("%s: failed to write to fn 0xf1 %d\n",
				mmc_hostname(card->host), ret);
			goto out;
		}

		ret = mmc_io_rw_direct(card, 0, 0, 0xF0, 0, &settings);
		if (ret) {
			pr_crit("%s: failed to read fn 0xf0 %d\n",
			mmc_hostname(card->host), ret);
			goto out;
		}

		settings |= 0x20;
		ret = mmc_io_rw_direct(card, 1, 0, 0xF0, settings, NULL);
		if (ret) {
			pr_crit("%s: failed to write to fn 0xf0 %d\n",
				mmc_hostname(card->host), ret);
			goto out;
		}
	}
out:
	return;
}

static int sdio_enable_wide(struct mmc_card *card)
{
	int ret;
	u8 ctrl;

	if (!(card->host->caps & MMC_CAP_4_BIT_DATA))
	if (!(card->host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)))
		return 0;

	if (card->cccr.low_speed && !card->cccr.wide_bus)
@@ -223,6 +289,9 @@ static int sdio_enable_wide(struct mmc_card *card)

	/* set as 4-bit bus width */
	ctrl &= ~SDIO_BUS_WIDTH_MASK;
	if (card->host->caps & MMC_CAP_8_BIT_DATA)
		ctrl |= SDIO_BUS_WIDTH_8BIT;
	else if (card->host->caps & MMC_CAP_4_BIT_DATA)
		ctrl |= SDIO_BUS_WIDTH_4BIT;

	ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_IF, ctrl, NULL);
@@ -264,7 +333,7 @@ static int sdio_disable_wide(struct mmc_card *card)
	int ret;
	u8 ctrl;

	if (!(card->host->caps & MMC_CAP_4_BIT_DATA))
	if (!(card->host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)))
		return 0;

	if (card->cccr.low_speed && !card->cccr.wide_bus)
@@ -274,10 +343,10 @@ static int sdio_disable_wide(struct mmc_card *card)
	if (ret)
		return ret;

	if (!(ctrl & SDIO_BUS_WIDTH_4BIT))
	if (!(ctrl & (SDIO_BUS_WIDTH_4BIT | SDIO_BUS_WIDTH_8BIT)))
		return 0;

	ctrl &= ~SDIO_BUS_WIDTH_4BIT;
	ctrl &= ~(SDIO_BUS_WIDTH_4BIT | SDIO_BUS_WIDTH_8BIT);
	ctrl |= SDIO_BUS_ASYNC_INT;

	ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_IF, ctrl, NULL);
@@ -495,6 +564,9 @@ static int sdio_set_bus_speed_mode(struct mmc_card *card)
	if (err)
		return err;

	/* Vendor specific settings based on card quirks */
	sdio_enable_vendor_specific_settings(card);

	speed &= ~SDIO_SPEED_BSS_MASK;
	speed |= bus_speed;
	err = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL);
@@ -790,7 +862,12 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
		 * Switch to wider bus (if supported).
		 */
		err = sdio_enable_4bit_bus(card);
		if (err)
		if (err > 0) {
			if (card->host->caps & MMC_CAP_8_BIT_DATA)
				mmc_set_bus_width(card->host, MMC_BUS_WIDTH_8);
			else if (card->host->caps & MMC_CAP_4_BIT_DATA)
				mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4);
		} else if (err)
			goto remove;
	}

@@ -988,6 +1065,13 @@ static int mmc_sdio_resume(struct mmc_host *host)
	} else if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) {
		/* We may have switched to 1-bit mode during suspend */
		err = sdio_enable_4bit_bus(host->card);
		if (err > 0) {
			if (host->caps & MMC_CAP_8_BIT_DATA)
				mmc_set_bus_width(host, MMC_BUS_WIDTH_8);
			else if (host->caps & MMC_CAP_4_BIT_DATA)
				mmc_set_bus_width(host, MMC_BUS_WIDTH_4);
			err = 0;
		}
	}

	if (err)
@@ -1008,6 +1092,7 @@ static int mmc_sdio_resume(struct mmc_host *host)
	mmc_release_host(host);

	host->pm_flags &= ~MMC_PM_KEEP_POWER;
	host->pm_flags &= ~MMC_PM_WAKE_SDIO_IRQ;
	return err;
}

+8 −2
Original line number Diff line number Diff line
@@ -278,9 +278,15 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func)
			break;

		/* null entries have no link field or data */
		if (tpl_code == 0x00)
		if (tpl_code == 0x00) {
			if (card->cis.vendor == 0x70 &&
				(card->cis.device == 0x2460 ||
				card->cis.device == 0x0460 ||
				card->cis.device == 0x23F1 ||
				card->cis.device == 0x23F0))
				break;
			continue;

		}
		ret = mmc_io_rw_direct(card, 0, 0, ptr++, 0, &tpl_link);
		if (ret)
			break;
Loading