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

Commit 26daa1ed authored by Jennifer Li's avatar Jennifer Li Committed by Chris Ball
Browse files

mmc: sdhci: Disable ADMA on some O2Micro SD/MMC parts.



This patch disables the broken ADMA on selected O2Micro devices.

Signed-off-by: default avatarJennifer Li <Jennifer.li@o2micro.com>
Reviewed-by: default avatarChris Ball <cjb@laptop.org>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent 17d8020d
Loading
Loading
Loading
Loading
+112 −0
Original line number Diff line number Diff line
@@ -176,6 +176,74 @@ static const struct sdhci_pci_fixes sdhci_intel_mfd_emmc_sdio = {
	.quirks		= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
};

/* O2Micro extra registers */
#define O2_SD_LOCK_WP		0xD3
#define O2_SD_MULTI_VCC3V	0xEE
#define O2_SD_CLKREQ		0xEC
#define O2_SD_CAPS		0xE0
#define O2_SD_ADMA1		0xE2
#define O2_SD_ADMA2		0xE7
#define O2_SD_INF_MOD		0xF1

static int o2_probe(struct sdhci_pci_chip *chip)
{
	int ret;
	u8 scratch;

	switch (chip->pdev->device) {
	case PCI_DEVICE_ID_O2_8220:
	case PCI_DEVICE_ID_O2_8221:
	case PCI_DEVICE_ID_O2_8320:
	case PCI_DEVICE_ID_O2_8321:
		/* This extra setup is required due to broken ADMA. */
		ret = pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch);
		if (ret)
			return ret;
		scratch &= 0x7f;
		pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);

		/* Set Multi 3 to VCC3V# */
		pci_write_config_byte(chip->pdev, O2_SD_MULTI_VCC3V, 0x08);

		/* Disable CLK_REQ# support after media DET */
		ret = pci_read_config_byte(chip->pdev, O2_SD_CLKREQ, &scratch);
		if (ret)
			return ret;
		scratch |= 0x20;
		pci_write_config_byte(chip->pdev, O2_SD_CLKREQ, scratch);

		/* Choose capabilities, enable SDMA.  We have to write 0x01
		 * to the capabilities register first to unlock it.
		 */
		ret = pci_read_config_byte(chip->pdev, O2_SD_CAPS, &scratch);
		if (ret)
			return ret;
		scratch |= 0x01;
		pci_write_config_byte(chip->pdev, O2_SD_CAPS, scratch);
		pci_write_config_byte(chip->pdev, O2_SD_CAPS, 0x73);

		/* Disable ADMA1/2 */
		pci_write_config_byte(chip->pdev, O2_SD_ADMA1, 0x39);
		pci_write_config_byte(chip->pdev, O2_SD_ADMA2, 0x08);

		/* Disable the infinite transfer mode */
		ret = pci_read_config_byte(chip->pdev, O2_SD_INF_MOD, &scratch);
		if (ret)
			return ret;
		scratch |= 0x08;
		pci_write_config_byte(chip->pdev, O2_SD_INF_MOD, scratch);

		/* Lock WP */
		ret = pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch);
		if (ret)
			return ret;
		scratch |= 0x80;
		pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch);
	}

	return 0;
}

static int jmicron_pmos(struct sdhci_pci_chip *chip, int on)
{
	u8 scratch;
@@ -339,6 +407,10 @@ static int jmicron_resume(struct sdhci_pci_chip *chip)
	return 0;
}

static const struct sdhci_pci_fixes sdhci_o2 = {
	.probe		= o2_probe,
};

static const struct sdhci_pci_fixes sdhci_jmicron = {
	.probe		= jmicron_probe,

@@ -589,6 +661,46 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
		.driver_data	= (kernel_ulong_t)&sdhci_intel_mfd_emmc_sdio,
	},

	{
		.vendor		= PCI_VENDOR_ID_O2,
		.device		= PCI_DEVICE_ID_O2_8120,
		.subvendor	= PCI_ANY_ID,
		.subdevice	= PCI_ANY_ID,
		.driver_data	= (kernel_ulong_t)&sdhci_o2,
	},

	{
		.vendor		= PCI_VENDOR_ID_O2,
		.device		= PCI_DEVICE_ID_O2_8220,
		.subvendor	= PCI_ANY_ID,
		.subdevice	= PCI_ANY_ID,
		.driver_data	= (kernel_ulong_t)&sdhci_o2,
	},

	{
		.vendor		= PCI_VENDOR_ID_O2,
		.device		= PCI_DEVICE_ID_O2_8221,
		.subvendor	= PCI_ANY_ID,
		.subdevice	= PCI_ANY_ID,
		.driver_data	= (kernel_ulong_t)&sdhci_o2,
	},

	{
		.vendor		= PCI_VENDOR_ID_O2,
		.device		= PCI_DEVICE_ID_O2_8320,
		.subvendor	= PCI_ANY_ID,
		.subdevice	= PCI_ANY_ID,
		.driver_data	= (kernel_ulong_t)&sdhci_o2,
	},

	{
		.vendor		= PCI_VENDOR_ID_O2,
		.device		= PCI_DEVICE_ID_O2_8321,
		.subvendor	= PCI_ANY_ID,
		.subdevice	= PCI_ANY_ID,
		.driver_data	= (kernel_ulong_t)&sdhci_o2,
	},

	{	/* Generic SD host controller */
		PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
	},
+5 −0
Original line number Diff line number Diff line
@@ -1650,6 +1650,11 @@
#define PCI_DEVICE_ID_O2_6836		0x6836
#define PCI_DEVICE_ID_O2_6812		0x6872
#define PCI_DEVICE_ID_O2_6933		0x6933
#define PCI_DEVICE_ID_O2_8120		0x8120
#define PCI_DEVICE_ID_O2_8220		0x8220
#define PCI_DEVICE_ID_O2_8221		0x8221
#define PCI_DEVICE_ID_O2_8320		0x8320
#define PCI_DEVICE_ID_O2_8321		0x8321

#define PCI_VENDOR_ID_3DFX		0x121a
#define PCI_DEVICE_ID_3DFX_VOODOO	0x0001