瀏覽代碼

sdhci: toggle JMicron PMOS setting

Some of the JMicron chips requires us to manually enable the power
output stages of the chip. Add the necessary hooks and functions to
manage this.

Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Pierre Ossman 17 年之前
父節點
當前提交
45211e2159
共有 1 個文件被更改,包括 67 次插入0 次删除
  1. 67 0
      drivers/mmc/host/sdhci-pci.c

+ 67 - 0
drivers/mmc/host/sdhci-pci.c

@@ -44,6 +44,8 @@ struct sdhci_pci_fixes {
 	unsigned int		quirks;
 	unsigned int		quirks;
 
 
 	int			(*probe)(struct sdhci_pci_chip*);
 	int			(*probe)(struct sdhci_pci_chip*);
+
+	int			(*resume)(struct sdhci_pci_chip*);
 };
 };
 
 
 struct sdhci_pci_slot {
 struct sdhci_pci_slot {
@@ -101,10 +103,69 @@ static const struct sdhci_pci_fixes sdhci_cafe = {
 			  SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
 			  SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
 };
 };
 
 
+static int jmicron_pmos(struct sdhci_pci_chip *chip, int on)
+{
+	u8 scratch;
+	int ret;
+
+	ret = pci_read_config_byte(chip->pdev, 0xAE, &scratch);
+	if (ret)
+		return ret;
+
+	/*
+	 * Turn PMOS on [bit 0], set over current detection to 2.4 V
+	 * [bit 1:2] and enable over current debouncing [bit 6].
+	 */
+	if (on)
+		scratch |= 0x47;
+	else
+		scratch &= ~0x47;
+
+	ret = pci_write_config_byte(chip->pdev, 0xAE, scratch);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int jmicron_probe(struct sdhci_pci_chip *chip)
+{
+	int ret;
+
+	/*
+	 * JMicron chips need a bit of a nudge to enable the power
+	 * output pins.
+	 */
+	ret = jmicron_pmos(chip, 1);
+	if (ret) {
+		dev_err(&chip->pdev->dev, "Failure enabling card power\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int jmicron_resume(struct sdhci_pci_chip *chip)
+{
+	int ret;
+
+	ret = jmicron_pmos(chip, 1);
+	if (ret) {
+		dev_err(&chip->pdev->dev, "Failure enabling card power\n");
+		return ret;
+	}
+
+	return 0;
+}
+
 static const struct sdhci_pci_fixes sdhci_jmicron = {
 static const struct sdhci_pci_fixes sdhci_jmicron = {
 	.quirks		= SDHCI_QUIRK_32BIT_DMA_ADDR |
 	.quirks		= SDHCI_QUIRK_32BIT_DMA_ADDR |
 			  SDHCI_QUIRK_32BIT_DMA_SIZE |
 			  SDHCI_QUIRK_32BIT_DMA_SIZE |
 			  SDHCI_QUIRK_RESET_AFTER_REQUEST,
 			  SDHCI_QUIRK_RESET_AFTER_REQUEST,
+
+	.probe		= jmicron_probe,
+
+	.resume		= jmicron_resume,
 };
 };
 
 
 static const struct pci_device_id pci_ids[] __devinitdata = {
 static const struct pci_device_id pci_ids[] __devinitdata = {
@@ -264,6 +325,12 @@ static int sdhci_pci_resume (struct pci_dev *pdev)
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
+	if (chip->fixes && chip->fixes->resume) {
+		ret = chip->fixes->resume(chip);
+		if (ret)
+			return ret;
+	}
+
 	for (i = 0;i < chip->num_slots;i++) {
 	for (i = 0;i < chip->num_slots;i++) {
 		slot = chip->slots[i];
 		slot = chip->slots[i];
 		if (!slot)
 		if (!slot)