diff options
Diffstat (limited to 'sys/dev/sdhci/sdhci.c')
-rw-r--r-- | sys/dev/sdhci/sdhci.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/sys/dev/sdhci/sdhci.c b/sys/dev/sdhci/sdhci.c index e071155..0bbf608 100644 --- a/sys/dev/sdhci/sdhci.c +++ b/sys/dev/sdhci/sdhci.c @@ -74,6 +74,8 @@ __FBSDID("$FreeBSD$"); #define SDHCI_QUIRK_INCR_TIMEOUT_CONTROL (1<<7) /* Controller has broken read timings */ #define SDHCI_QUIRK_BROKEN_TIMINGS (1<<8) +/* Controller needs lowered frequency */ +#define SDHCI_QUIRK_LOWER_FREQUENCY (1<<9) static const struct sdhci_device { uint32_t model; @@ -85,6 +87,8 @@ static const struct sdhci_device { SDHCI_QUIRK_FORCE_DMA }, { 0xe8221180, 0xffff, "RICOH SD", SDHCI_QUIRK_FORCE_DMA }, + { 0xe8231180, 0xffff, "RICOH R5CE823 SD", + SDHCI_QUIRK_LOWER_FREQUENCY }, { 0x8034104c, 0xffff, "TI XX21/XX11 SD", SDHCI_QUIRK_FORCE_DMA }, { 0x05501524, 0xffff, "ENE CB712 SD", @@ -350,6 +354,24 @@ sdhci_init(struct sdhci_slot *slot) } static void +sdhci_lower_frequency(device_t dev) +{ + + /* Enable SD2.0 mode. */ + pci_write_config(dev, SDHC_PCI_MODE_KEY, 0xfc, 1); + pci_write_config(dev, SDHC_PCI_MODE, SDHC_PCI_MODE_SD20, 1); + pci_write_config(dev, SDHC_PCI_MODE_KEY, 0x00, 1); + + /* + * Some SD/MMC cards don't work with the default base + * clock frequency of 200MHz. Lower it to 50Hz. + */ + pci_write_config(dev, SDHC_PCI_BASE_FREQ_KEY, 0x01, 1); + pci_write_config(dev, SDHC_PCI_BASE_FREQ, 50, 1); + pci_write_config(dev, SDHC_PCI_BASE_FREQ_KEY, 0x00, 1); +} + +static void sdhci_set_clock(struct sdhci_slot *slot, uint32_t clock) { uint32_t res; @@ -631,6 +653,9 @@ sdhci_attach(device_t dev) break; } } + /* Some controllers need to be bumped into the right mode. */ + if (sc->quirks & SDHCI_QUIRK_LOWER_FREQUENCY) + sdhci_lower_frequency(dev); /* Read slots info from PCI registers. */ slots = pci_read_config(dev, PCI_SLOT_INFO, 1); bar = PCI_SLOT_INFO_FIRST_BAR(slots); |