summaryrefslogtreecommitdiffstats
path: root/sys/dev/pci/rtsx_pci.c
diff options
context:
space:
mode:
authorstsp <stsp@openbsd.org>2012-11-29 23:36:34 +0000
committerstsp <stsp@openbsd.org>2012-11-29 23:36:34 +0000
commitf615cd67b44e84976c75886093ca5794b1689fea (patch)
tree32cb893c341e137c6f7cb57ef28eba7357667fe4 /sys/dev/pci/rtsx_pci.c
parentDelete needless check for NULL. From Michael W. Bombardieri. (diff)
downloadwireguard-openbsd-f615cd67b44e84976c75886093ca5794b1689fea.tar.xz
wireguard-openbsd-f615cd67b44e84976c75886093ca5794b1689fea.zip
Add rtsx(4), a new driver for the Realtek RTS5209 card reader.
This card reader does not comply to the standard SDHC interface supported by sdhc(4) and hence requires a custom driver. With help from uwe and mikeb. Useful hints were also provided by the author of the corresponding Linux driver (wwang at realsil com cn), thanks a lot! Tested by myself and weerd on i386 and amd64.
Diffstat (limited to 'sys/dev/pci/rtsx_pci.c')
-rw-r--r--sys/dev/pci/rtsx_pci.c105
1 files changed, 105 insertions, 0 deletions
diff --git a/sys/dev/pci/rtsx_pci.c b/sys/dev/pci/rtsx_pci.c
new file mode 100644
index 00000000000..127f43f341a
--- /dev/null
+++ b/sys/dev/pci/rtsx_pci.c
@@ -0,0 +1,105 @@
+/* $OpenBSD: rtsx_pci.c,v 1.1 2012/11/29 23:36:34 stsp Exp $ */
+
+/*
+ * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
+ * Copyright (c) 2012 Stefan Sperling <stsp@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+#include <dev/ic/rtsxreg.h>
+#include <dev/ic/rtsxvar.h>
+#include <dev/sdmmc/sdmmcvar.h>
+
+#define RTSX_PCI_BAR 0x10
+
+struct rtsx_pci_softc {
+ struct rtsx_softc sc;
+ void *sc_ih;
+};
+
+int rtsx_pci_match(struct device *, void *, void *);
+void rtsx_pci_attach(struct device *, struct device *, void *);
+
+struct cfattach rtsx_pci_ca = {
+ sizeof(struct rtsx_pci_softc), rtsx_pci_match, rtsx_pci_attach,
+ NULL, rtsx_activate
+};
+
+int
+rtsx_pci_match(struct device *parent, void *match, void *aux)
+{
+ struct pci_attach_args *pa = aux;
+
+ if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_REALTEK &&
+ PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_REALTEK_RTS5209)
+ return 1;
+
+ return 0;
+}
+
+void
+rtsx_pci_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct rtsx_pci_softc *sc = (struct rtsx_pci_softc *)self;
+ struct pci_attach_args *pa = aux;
+ pci_intr_handle_t ih;
+ char const *intrstr;
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh;
+ bus_size_t size;
+
+ if ((pci_conf_read(pa->pa_pc, pa->pa_tag, RTSX_CFG_PCI)
+ & RTSX_CFG_ASIC) != 0) {
+ printf("%s: no asic\n", sc->sc.sc_dev.dv_xname);
+ return;
+ }
+
+ if (pci_intr_map(pa, &ih)) {
+ printf(": can't map interrupt\n");
+ return;
+ }
+
+ intrstr = pci_intr_string(pa->pa_pc, ih);
+ sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_SDMMC,
+ rtsx_intr, sc, sc->sc.sc_dev.dv_xname);
+ if (sc->sc_ih == NULL) {
+ printf(": can't establish interrupt\n");
+ return;
+ }
+ printf(": %s\n", intrstr);
+
+ if (pci_mem_find(pa->pa_pc, pa->pa_tag, RTSX_PCI_BAR,
+ NULL, NULL, NULL) != 0) {
+ printf("%s: can't find registers\n", sc->sc.sc_dev.dv_xname);
+ return;
+ }
+
+ if (pci_mapreg_map(pa, RTSX_PCI_BAR, PCI_MAPREG_TYPE_MEM, 0,
+ &iot, &ioh, NULL, &size, 0)) {
+ printf("%s: can't map registers\n", sc->sc.sc_dev.dv_xname);
+ return;
+ }
+
+ pci_set_powerstate(pa->pa_pc, pa->pa_tag, PCI_PMCSR_STATE_D0);
+
+ if (rtsx_attach(&sc->sc, iot, ioh, size, pa->pa_dmat) != 0)
+ printf("%s: can't initialize chip\n", sc->sc.sc_dev.dv_xname);
+}