Loading drivers/mmc/host/sdhci-pci-data.c +3 −0 Original line number Diff line number Diff line Loading @@ -3,3 +3,6 @@ struct sdhci_pci_data *(*sdhci_pci_get_data)(struct pci_dev *pdev, int slotno); EXPORT_SYMBOL_GPL(sdhci_pci_get_data); int sdhci_pci_spt_drive_strength; EXPORT_SYMBOL_GPL(sdhci_pci_spt_drive_strength); drivers/mmc/host/sdhci-pci.c +83 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <linux/slab.h> #include <linux/device.h> #include <linux/mmc/host.h> #include <linux/mmc/mmc.h> #include <linux/scatterlist.h> #include <linux/io.h> #include <linux/gpio.h> Loading Loading @@ -266,6 +267,69 @@ static void sdhci_pci_int_hw_reset(struct sdhci_host *host) usleep_range(300, 1000); } static int spt_select_drive_strength(struct sdhci_host *host, struct mmc_card *card, unsigned int max_dtr, int host_drv, int card_drv, int *drv_type) { int drive_strength; if (sdhci_pci_spt_drive_strength > 0) drive_strength = sdhci_pci_spt_drive_strength & 0xf; else drive_strength = 1; /* 33-ohm */ if ((mmc_driver_type_mask(drive_strength) & card_drv) == 0) drive_strength = 0; /* Default 50-ohm */ return drive_strength; } /* Try to read the drive strength from the card */ static void spt_read_drive_strength(struct sdhci_host *host) { u32 val, i, t; u16 m; if (sdhci_pci_spt_drive_strength) return; sdhci_pci_spt_drive_strength = -1; m = sdhci_readw(host, SDHCI_HOST_CONTROL2) & 0x7; if (m != 3 && m != 5) return; val = sdhci_readl(host, SDHCI_PRESENT_STATE); if (val & 0x3) return; sdhci_writel(host, 0x007f0023, SDHCI_INT_ENABLE); sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); sdhci_writew(host, 0x10, SDHCI_TRANSFER_MODE); sdhci_writeb(host, 0xe, SDHCI_TIMEOUT_CONTROL); sdhci_writew(host, 512, SDHCI_BLOCK_SIZE); sdhci_writew(host, 1, SDHCI_BLOCK_COUNT); sdhci_writel(host, 0, SDHCI_ARGUMENT); sdhci_writew(host, 0x83b, SDHCI_COMMAND); for (i = 0; i < 1000; i++) { val = sdhci_readl(host, SDHCI_INT_STATUS); if (val & 0xffff8000) return; if (val & 0x20) break; udelay(1); } val = sdhci_readl(host, SDHCI_PRESENT_STATE); if (!(val & 0x800)) return; for (i = 0; i < 47; i++) val = sdhci_readl(host, SDHCI_BUFFER); t = val & 0xf00; if (t != 0x200 && t != 0x300) return; sdhci_pci_spt_drive_strength = 0x10 | ((val >> 12) & 0xf); } static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot) { slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE | Loading @@ -276,6 +340,10 @@ static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot) slot->hw_reset = sdhci_pci_int_hw_reset; if (slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_BSW_EMMC) slot->host->timeout_clk = 1000; /* 1000 kHz i.e. 1 MHz */ if (slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_SPT_EMMC) { spt_read_drive_strength(slot->host); slot->select_drive_strength = spt_select_drive_strength; } return 0; } Loading Loading @@ -1203,6 +1271,20 @@ static void sdhci_pci_hw_reset(struct sdhci_host *host) slot->hw_reset(host); } static int sdhci_pci_select_drive_strength(struct sdhci_host *host, struct mmc_card *card, unsigned int max_dtr, int host_drv, int card_drv, int *drv_type) { struct sdhci_pci_slot *slot = sdhci_priv(host); if (!slot->select_drive_strength) return 0; return slot->select_drive_strength(host, card, max_dtr, host_drv, card_drv, drv_type); } static const struct sdhci_ops sdhci_pci_ops = { .set_clock = sdhci_set_clock, .enable_dma = sdhci_pci_enable_dma, Loading @@ -1210,6 +1292,7 @@ static const struct sdhci_ops sdhci_pci_ops = { .reset = sdhci_reset, .set_uhs_signaling = sdhci_set_uhs_signaling, .hw_reset = sdhci_pci_hw_reset, .select_drive_strength = sdhci_pci_select_drive_strength, }; /*****************************************************************************\ Loading drivers/mmc/host/sdhci-pci.h +4 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,10 @@ struct sdhci_pci_slot { bool cd_override_level; void (*hw_reset)(struct sdhci_host *host); int (*select_drive_strength)(struct sdhci_host *host, struct mmc_card *card, unsigned int max_dtr, int host_drv, int card_drv, int *drv_type); }; struct sdhci_pci_chip { Loading include/linux/mmc/sdhci-pci-data.h +2 −0 Original line number Diff line number Diff line Loading @@ -15,4 +15,6 @@ struct sdhci_pci_data { extern struct sdhci_pci_data *(*sdhci_pci_get_data)(struct pci_dev *pdev, int slotno); extern int sdhci_pci_spt_drive_strength; #endif Loading
drivers/mmc/host/sdhci-pci-data.c +3 −0 Original line number Diff line number Diff line Loading @@ -3,3 +3,6 @@ struct sdhci_pci_data *(*sdhci_pci_get_data)(struct pci_dev *pdev, int slotno); EXPORT_SYMBOL_GPL(sdhci_pci_get_data); int sdhci_pci_spt_drive_strength; EXPORT_SYMBOL_GPL(sdhci_pci_spt_drive_strength);
drivers/mmc/host/sdhci-pci.c +83 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <linux/slab.h> #include <linux/device.h> #include <linux/mmc/host.h> #include <linux/mmc/mmc.h> #include <linux/scatterlist.h> #include <linux/io.h> #include <linux/gpio.h> Loading Loading @@ -266,6 +267,69 @@ static void sdhci_pci_int_hw_reset(struct sdhci_host *host) usleep_range(300, 1000); } static int spt_select_drive_strength(struct sdhci_host *host, struct mmc_card *card, unsigned int max_dtr, int host_drv, int card_drv, int *drv_type) { int drive_strength; if (sdhci_pci_spt_drive_strength > 0) drive_strength = sdhci_pci_spt_drive_strength & 0xf; else drive_strength = 1; /* 33-ohm */ if ((mmc_driver_type_mask(drive_strength) & card_drv) == 0) drive_strength = 0; /* Default 50-ohm */ return drive_strength; } /* Try to read the drive strength from the card */ static void spt_read_drive_strength(struct sdhci_host *host) { u32 val, i, t; u16 m; if (sdhci_pci_spt_drive_strength) return; sdhci_pci_spt_drive_strength = -1; m = sdhci_readw(host, SDHCI_HOST_CONTROL2) & 0x7; if (m != 3 && m != 5) return; val = sdhci_readl(host, SDHCI_PRESENT_STATE); if (val & 0x3) return; sdhci_writel(host, 0x007f0023, SDHCI_INT_ENABLE); sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); sdhci_writew(host, 0x10, SDHCI_TRANSFER_MODE); sdhci_writeb(host, 0xe, SDHCI_TIMEOUT_CONTROL); sdhci_writew(host, 512, SDHCI_BLOCK_SIZE); sdhci_writew(host, 1, SDHCI_BLOCK_COUNT); sdhci_writel(host, 0, SDHCI_ARGUMENT); sdhci_writew(host, 0x83b, SDHCI_COMMAND); for (i = 0; i < 1000; i++) { val = sdhci_readl(host, SDHCI_INT_STATUS); if (val & 0xffff8000) return; if (val & 0x20) break; udelay(1); } val = sdhci_readl(host, SDHCI_PRESENT_STATE); if (!(val & 0x800)) return; for (i = 0; i < 47; i++) val = sdhci_readl(host, SDHCI_BUFFER); t = val & 0xf00; if (t != 0x200 && t != 0x300) return; sdhci_pci_spt_drive_strength = 0x10 | ((val >> 12) & 0xf); } static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot) { slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE | Loading @@ -276,6 +340,10 @@ static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot) slot->hw_reset = sdhci_pci_int_hw_reset; if (slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_BSW_EMMC) slot->host->timeout_clk = 1000; /* 1000 kHz i.e. 1 MHz */ if (slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_SPT_EMMC) { spt_read_drive_strength(slot->host); slot->select_drive_strength = spt_select_drive_strength; } return 0; } Loading Loading @@ -1203,6 +1271,20 @@ static void sdhci_pci_hw_reset(struct sdhci_host *host) slot->hw_reset(host); } static int sdhci_pci_select_drive_strength(struct sdhci_host *host, struct mmc_card *card, unsigned int max_dtr, int host_drv, int card_drv, int *drv_type) { struct sdhci_pci_slot *slot = sdhci_priv(host); if (!slot->select_drive_strength) return 0; return slot->select_drive_strength(host, card, max_dtr, host_drv, card_drv, drv_type); } static const struct sdhci_ops sdhci_pci_ops = { .set_clock = sdhci_set_clock, .enable_dma = sdhci_pci_enable_dma, Loading @@ -1210,6 +1292,7 @@ static const struct sdhci_ops sdhci_pci_ops = { .reset = sdhci_reset, .set_uhs_signaling = sdhci_set_uhs_signaling, .hw_reset = sdhci_pci_hw_reset, .select_drive_strength = sdhci_pci_select_drive_strength, }; /*****************************************************************************\ Loading
drivers/mmc/host/sdhci-pci.h +4 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,10 @@ struct sdhci_pci_slot { bool cd_override_level; void (*hw_reset)(struct sdhci_host *host); int (*select_drive_strength)(struct sdhci_host *host, struct mmc_card *card, unsigned int max_dtr, int host_drv, int card_drv, int *drv_type); }; struct sdhci_pci_chip { Loading
include/linux/mmc/sdhci-pci-data.h +2 −0 Original line number Diff line number Diff line Loading @@ -15,4 +15,6 @@ struct sdhci_pci_data { extern struct sdhci_pci_data *(*sdhci_pci_get_data)(struct pci_dev *pdev, int slotno); extern int sdhci_pci_spt_drive_strength; #endif