diff options
author | Federico G. Schwindt <fgsch@cvs.openbsd.org> | 2006-07-18 17:28:15 +0000 |
---|---|---|
committer | Federico G. Schwindt <fgsch@cvs.openbsd.org> | 2006-07-18 17:28:15 +0000 |
commit | 91ee0c64cd182294f51d92fcac46a910d9baf016 (patch) | |
tree | 226a07f082cc19c56bfd2b85c9ff2104b96c9d5b /sys/dev/pci | |
parent | ee89b6dd44105f4b5edefd527dde2e41ddd84f95 (diff) |
On some TI controllers, disable the SD/MMC bit on the flash media so
the SD host takes over. originally fix from ian@, different one commited.
tested by ian@ and myself. uwe@ ok.
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/sdhc_pci.c | 35 |
1 files changed, 34 insertions, 1 deletions
diff --git a/sys/dev/pci/sdhc_pci.c b/sys/dev/pci/sdhc_pci.c index 605b0b436f9..723ec223eb2 100644 --- a/sys/dev/pci/sdhc_pci.c +++ b/sys/dev/pci/sdhc_pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sdhc_pci.c,v 1.3 2006/07/17 20:48:26 fgsch Exp $ */ +/* $OpenBSD: sdhc_pci.c,v 1.4 2006/07/18 17:28:14 fgsch Exp $ */ /* * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org> @@ -22,6 +22,7 @@ #include <sys/malloc.h> #include <dev/pci/pcivar.h> +#include <dev/pci/pcidevs.h> #include <dev/sdmmc/sdhcreg.h> #include <dev/sdmmc/sdhcvar.h> #include <dev/sdmmc/sdmmcvar.h> @@ -34,6 +35,10 @@ #define SDHC_PCI_NUM_SLOTS(info) ((((info) >> 4) & 0x7) + 1) #define SDHC_PCI_FIRST_BAR(info) ((info) & 0x7) +/* TI specific register */ +#define SDHC_PCI_GENERAL_CTL 0x4c +#define MMC_SD_DIS 0x02 + struct sdhc_pci_softc { struct sdhc_softc sc; void *sc_ih; @@ -41,6 +46,7 @@ struct sdhc_pci_softc { int sdhc_pci_match(struct device *, void *, void *); void sdhc_pci_attach(struct device *, struct device *, void *); +void sdhc_takecontroller(struct pci_attach_args *); struct cfattach sdhc_pci_ca = { sizeof(struct sdhc_pci_softc), sdhc_pci_match, sdhc_pci_attach @@ -73,6 +79,12 @@ sdhc_pci_attach(struct device *parent, struct device *self, void *aux) bus_space_handle_t ioh; bus_size_t size; + /* Some TI controllers needs special treatment. */ + if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_TI && + PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_TI_PCI7XX1_FLASH && + pa->pa_function == 4) + sdhc_takecontroller(pa); + if (pci_intr_map(pa, &ih)) { printf(": can't map interrupt\n"); return; @@ -130,3 +142,24 @@ sdhc_pci_attach(struct device *parent, struct device *self, void *aux) (void)powerhook_establish(sdhc_power, &sc->sc); (void)shutdownhook_establish(sdhc_shutdown, &sc->sc); } + +void +sdhc_takecontroller(struct pci_attach_args *pa) +{ + pcitag_t tag; + pcireg_t id, reg; + + /* Look at func 3 for the flash device */ + tag = pci_make_tag(pa->pa_pc, pa->pa_bus, pa->pa_device, 3); + id = pci_conf_read(pa->pa_pc, tag, PCI_ID_REG); + if (PCI_PRODUCT(id) != PCI_PRODUCT_TI_PCI7XX1_FLASH) + return; + + /* + * Disable MMC/SD on the flash media controller so the + * SD host takes over. + */ + reg = pci_conf_read(pa->pa_pc, tag, SDHC_PCI_GENERAL_CTL); + reg |= MMC_SD_DIS; + pci_conf_write(pa->pa_pc, tag, SDHC_PCI_GENERAL_CTL, reg); +} |