summaryrefslogtreecommitdiff
path: root/sys/dev/pci/sdhc_pci.c
diff options
context:
space:
mode:
authorFederico G. Schwindt <fgsch@cvs.openbsd.org>2006-07-18 17:28:15 +0000
committerFederico G. Schwindt <fgsch@cvs.openbsd.org>2006-07-18 17:28:15 +0000
commit91ee0c64cd182294f51d92fcac46a910d9baf016 (patch)
tree226a07f082cc19c56bfd2b85c9ff2104b96c9d5b /sys/dev/pci/sdhc_pci.c
parentee89b6dd44105f4b5edefd527dde2e41ddd84f95 (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/sdhc_pci.c')
-rw-r--r--sys/dev/pci/sdhc_pci.c35
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);
+}