summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorstsp <stsp@openbsd.org>2013-11-06 13:51:02 +0000
committerstsp <stsp@openbsd.org>2013-11-06 13:51:02 +0000
commit0cd9a838eb1d6c96dcf7af6a68bdd15b51beb19e (patch)
treec9dde744f706cb1f833e94f018d347b9e2a8d529 /sys
parentteach the side-effect free drivers about the partition they are dealing (diff)
downloadwireguard-openbsd-0cd9a838eb1d6c96dcf7af6a68bdd15b51beb19e.tar.xz
wireguard-openbsd-0cd9a838eb1d6c96dcf7af6a68bdd15b51beb19e.zip
Add support for the RTS5229 card reader to rtsx(4).
From Pedro Martelletto.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ic/rtsx.c115
-rw-r--r--sys/dev/ic/rtsxreg.h34
-rw-r--r--sys/dev/ic/rtsxvar.h7
-rw-r--r--sys/dev/pci/rtsx_pci.c19
4 files changed, 145 insertions, 30 deletions
diff --git a/sys/dev/ic/rtsx.c b/sys/dev/ic/rtsx.c
index a584d6a7ca9..a38c14f8662 100644
--- a/sys/dev/ic/rtsx.c
+++ b/sys/dev/ic/rtsx.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtsx.c,v 1.4 2013/05/31 21:28:31 deraadt Exp $ */
+/* $OpenBSD: rtsx.c,v 1.5 2013/11/06 13:51:02 stsp Exp $ */
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
@@ -18,7 +18,7 @@
*/
/*
- * Realtek RTS5209 Card Reader driver.
+ * Realtek RTS5209/RTS5229 Card Reader driver.
*/
#include <sys/param.h>
@@ -162,7 +162,7 @@ struct cfdriver rtsx_cd = {
*/
int
rtsx_attach(struct rtsx_softc *sc, bus_space_tag_t iot,
- bus_space_handle_t ioh, bus_size_t iosize, bus_dma_tag_t dmat)
+ bus_space_handle_t ioh, bus_size_t iosize, bus_dma_tag_t dmat, int flags)
{
struct sdmmcbus_attach_args saa;
u_int32_t sdio_cfg;
@@ -170,6 +170,7 @@ rtsx_attach(struct rtsx_softc *sc, bus_space_tag_t iot,
sc->iot = iot;
sc->ioh = ioh;
sc->dmat = dmat;
+ sc->flags = flags;
if (rtsx_init(sc, 1))
return 1;
@@ -214,6 +215,25 @@ int
rtsx_init(struct rtsx_softc *sc, int attaching)
{
u_int32_t status;
+ u_int8_t version;
+ int error;
+
+ /* Read IC version from dummy register. */
+ if (sc->flags & RTSX_F_5229) {
+ RTSX_READ(sc, RTSX_DUMMY_REG, &version);
+ switch (version & 0x0F) {
+ case RTSX_IC_VERSION_A:
+ case RTSX_IC_VERSION_B:
+ case RTSX_IC_VERSION_D:
+ break;
+ case RTSX_IC_VERSION_C:
+ sc->flags |= RTSX_F_5229_TYPE_C;
+ break;
+ default:
+ printf("rtsx_init: unknown ic %02x\n", version);
+ return (1);
+ }
+ }
/* Enable interrupt write-clear (default is read-clear). */
RTSX_CLR(sc, RTSX_NFTS_TX_CTRL, RTSX_INT_READ_CLR);
@@ -235,7 +255,11 @@ rtsx_init(struct rtsx_softc *sc, int attaching)
delay(200);
/* XXX magic numbers from linux driver */
- if (rtsx_write_phy(sc, 0x00, 0xB966)) {
+ if (sc->flags & RTSX_F_5209)
+ error = rtsx_write_phy(sc, 0x00, 0xB966);
+ else
+ error = rtsx_write_phy(sc, 0x00, 0xBA42);
+ if (error) {
printf("%s: cannot write phy register\n", DEVNAME(sc));
return (1);
}
@@ -269,8 +293,17 @@ rtsx_init(struct rtsx_softc *sc, int attaching)
RTSX_SET(sc, RTSX_PETXCFG, RTSX_PETXCFG_CLKREQ_PIN);
/* Set up LED GPIO. */
- RTSX_WRITE(sc, RTSX_CARD_GPIO, 0x03);
- RTSX_WRITE(sc, RTSX_CARD_GPIO_DIR, 0x03);
+ if (sc->flags & RTSX_F_5209) {
+ RTSX_WRITE(sc, RTSX_CARD_GPIO, 0x03);
+ RTSX_WRITE(sc, RTSX_CARD_GPIO_DIR, 0x03);
+ } else {
+ RTSX_SET(sc, RTSX_GPIO_CTL, RTSX_GPIO_LED_ON);
+ /* Switch LDO3318 source from DV33 to 3V3. */
+ RTSX_CLR(sc, RTSX_LDO_PWR_SEL, RTSX_LDO_PWR_SEL_DV33);
+ RTSX_SET(sc, RTSX_LDO_PWR_SEL, RTSX_LDO_PWR_SEL_3V3);
+ /* Set default OLT blink period. */
+ RTSX_SET(sc, RTSX_OLT_LED_CTL, RTSX_OLT_LED_PERIOD);
+ }
return (0);
}
@@ -310,17 +343,29 @@ rtsx_activate(struct device *self, int act)
int
rtsx_led_enable(struct rtsx_softc *sc)
{
- RTSX_CLR(sc, RTSX_CARD_GPIO, RTSX_CARD_GPIO_LED_OFF);
- RTSX_WRITE(sc, RTSX_CARD_AUTO_BLINK,
- RTSX_LED_BLINK_EN | RTSX_LED_BLINK_SPEED);
+ if (sc->flags & RTSX_F_5209) {
+ RTSX_CLR(sc, RTSX_CARD_GPIO, RTSX_CARD_GPIO_LED_OFF);
+ RTSX_WRITE(sc, RTSX_CARD_AUTO_BLINK,
+ RTSX_LED_BLINK_EN | RTSX_LED_BLINK_SPEED);
+ } else {
+ RTSX_SET(sc, RTSX_GPIO_CTL, RTSX_GPIO_LED_ON);
+ RTSX_SET(sc, RTSX_OLT_LED_CTL, RTSX_OLT_LED_AUTOBLINK);
+ }
+
return 0;
}
int
rtsx_led_disable(struct rtsx_softc *sc)
{
- RTSX_CLR(sc, RTSX_CARD_AUTO_BLINK, RTSX_LED_BLINK_EN);
- RTSX_WRITE(sc, RTSX_CARD_GPIO, RTSX_CARD_GPIO_LED_OFF);
+ if (sc->flags & RTSX_F_5209) {
+ RTSX_CLR(sc, RTSX_CARD_AUTO_BLINK, RTSX_LED_BLINK_EN);
+ RTSX_WRITE(sc, RTSX_CARD_GPIO, RTSX_CARD_GPIO_LED_OFF);
+ } else {
+ RTSX_CLR(sc, RTSX_OLT_LED_CTL, RTSX_OLT_LED_AUTOBLINK);
+ RTSX_CLR(sc, RTSX_GPIO_CTL, RTSX_GPIO_LED_ON);
+ }
+
return 0;
}
@@ -373,10 +418,17 @@ rtsx_card_detect(sdmmc_chipset_handle_t sch)
return ISSET(sc->flags, RTSX_F_CARD_PRESENT);
}
+/*
+ * Notice that the meaning of RTSX_PWR_GATE_CTRL changes between RTS5209 and
+ * RTS5229. In RTS5209 it is a mask of disabled power gates, while in RTS5229
+ * it is a mask of *enabled* gates.
+ */
+
int
rtsx_bus_power_off(struct rtsx_softc *sc)
{
int error;
+ u_int8_t disable3;
error = rtsx_stop_sd_clock(sc);
if (error)
@@ -386,14 +438,23 @@ rtsx_bus_power_off(struct rtsx_softc *sc)
RTSX_CLR(sc, RTSX_CARD_OE, RTSX_CARD_OUTPUT_EN);
/* Turn off power. */
- RTSX_SET(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_OFF);
+ disable3 = RTSX_PULL_CTL_DISABLE3;
+ if (sc->flags & RTSX_F_5209)
+ RTSX_SET(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_OFF);
+ else {
+ RTSX_CLR(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_VCC1 |
+ RTSX_LDO3318_VCC2);
+ if (sc->flags & RTSX_F_5229_TYPE_C)
+ disable3 = RTSX_PULL_CTL_DISABLE3_TYPE_C;
+ }
+
RTSX_SET(sc, RTSX_CARD_PWR_CTL, RTSX_SD_PWR_OFF);
RTSX_CLR(sc, RTSX_CARD_PWR_CTL, RTSX_PMOS_STRG_800mA);
/* Disable pull control. */
RTSX_WRITE(sc, RTSX_CARD_PULL_CTL1, RTSX_PULL_CTL_DISABLE12);
RTSX_WRITE(sc, RTSX_CARD_PULL_CTL2, RTSX_PULL_CTL_DISABLE12);
- RTSX_WRITE(sc, RTSX_CARD_PULL_CTL3, RTSX_PULL_CTL_DISABLE3);
+ RTSX_WRITE(sc, RTSX_CARD_PULL_CTL3, disable3);
return 0;
}
@@ -401,6 +462,8 @@ rtsx_bus_power_off(struct rtsx_softc *sc)
int
rtsx_bus_power_on(struct rtsx_softc *sc)
{
+ u_int8_t enable3;
+
/* Select SD card. */
RTSX_WRITE(sc, RTSX_CARD_SELECT, RTSX_SD_MOD_SEL);
RTSX_WRITE(sc, RTSX_CARD_SHARE_MODE, RTSX_CARD_SHARE_48_SD);
@@ -409,14 +472,32 @@ rtsx_bus_power_on(struct rtsx_softc *sc)
/* Enable pull control. */
RTSX_WRITE(sc, RTSX_CARD_PULL_CTL1, RTSX_PULL_CTL_ENABLE12);
RTSX_WRITE(sc, RTSX_CARD_PULL_CTL2, RTSX_PULL_CTL_ENABLE12);
- RTSX_WRITE(sc, RTSX_CARD_PULL_CTL3, RTSX_PULL_CTL_ENABLE3);
+ if (sc->flags & RTSX_F_5229_TYPE_C)
+ enable3 = RTSX_PULL_CTL_ENABLE3_TYPE_C;
+ else
+ enable3 = RTSX_PULL_CTL_ENABLE3;
+ RTSX_WRITE(sc, RTSX_CARD_PULL_CTL3, enable3);
- /* Enable card power. */
+ /*
+ * To avoid a current peak, enable card power in two phases with a
+ * delay in between.
+ */
+
+ /* Partial power. */
RTSX_SET(sc, RTSX_CARD_PWR_CTL, RTSX_SD_PARTIAL_PWR_ON);
- RTSX_SET(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_SUSPEND);
+ if (sc->flags & RTSX_F_5229)
+ RTSX_SET(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_VCC1);
+ else
+ RTSX_SET(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_SUSPEND);
+
delay(200);
+
+ /* Full power. */
RTSX_CLR(sc, RTSX_CARD_PWR_CTL, RTSX_SD_PWR_OFF);
- RTSX_CLR(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_OFF);
+ if (sc->flags & RTSX_F_5209)
+ RTSX_CLR(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_OFF);
+ else
+ RTSX_SET(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_VCC2);
/* Enable SD card output. */
RTSX_WRITE(sc, RTSX_CARD_OE, RTSX_SD_OUTPUT_EN);
diff --git a/sys/dev/ic/rtsxreg.h b/sys/dev/ic/rtsxreg.h
index b43348a47a0..d2260c328a8 100644
--- a/sys/dev/ic/rtsxreg.h
+++ b/sys/dev/ic/rtsxreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtsxreg.h,v 1.1 2012/11/29 23:36:34 stsp Exp $ */
+/* $OpenBSD: rtsxreg.h,v 1.2 2013/11/06 13:51:02 stsp Exp $ */
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
@@ -148,6 +148,14 @@
#define RTSX_RCCTL_F_400K 0x0
#define RTSX_RCCTL_F_2M 0x1
+/* RTS5229-only. */
+#define RTSX_OLT_LED_CTL 0xFC1E
+#define RTSX_OLT_LED_PERIOD 0x02
+#define RTSX_OLT_LED_AUTOBLINK 0x08
+
+#define RTSX_GPIO_CTL 0xFC1F
+#define RTSX_GPIO_LED_ON 0x02
+
/* Host controller commands. */
#define RTSX_READ_REG_CMD 0
#define RTSX_WRITE_REG_CMD 1
@@ -183,10 +191,12 @@
#define RTSX_CARD_PULL_CTL2 0xFD61
#define RTSX_CARD_PULL_CTL3 0xFD62
-#define RTSX_PULL_CTL_DISABLE12 0x55
-#define RTSX_PULL_CTL_DISABLE3 0xD5
-#define RTSX_PULL_CTL_ENABLE12 0xAA
-#define RTSX_PULL_CTL_ENABLE3 0xE9
+#define RTSX_PULL_CTL_DISABLE12 0x55
+#define RTSX_PULL_CTL_DISABLE3 0xD5
+#define RTSX_PULL_CTL_DISABLE3_TYPE_C 0xE5
+#define RTSX_PULL_CTL_ENABLE12 0xAA
+#define RTSX_PULL_CTL_ENABLE3 0xE9
+#define RTSX_PULL_CTL_ENABLE3_TYPE_C 0xD9
/* SD configuration register 1 (clock divider, bus mode and width). */
#define RTSX_SD_CFG1 0xFDA0
@@ -448,7 +458,12 @@
#define RTSX_LDO3318_ON 0x00
#define RTSX_LDO3318_SUSPEND 0x04
#define RTSX_LDO3318_OFF 0x06
+#define RTSX_LDO3318_VCC1 0x02
+#define RTSX_LDO3318_VCC2 0x04
#define RTSX_PWD_SUSPEND_EN 0xFE76
+#define RTSX_LDO_PWR_SEL 0xFE78
+#define RTSX_LDO_PWR_SEL_3V3 0x01
+#define RTSX_LDO_PWR_SEL_DV33 0x03
#define RTSX_PHY_RWCTL 0xFE3C
#define RTSX_PHY_READ 0x00
@@ -464,7 +479,7 @@
#define RTSX_PETXCFG 0xFE49
#define RTSX_PETXCFG_CLKREQ_PIN 0x08
-#define RTSX_CARD_AUTO_BLINK 0xFE56
+#define RTSX_CARD_AUTO_BLINK 0xFD56
#define RTSX_LED_BLINK_EN 0x08
#define RTSX_LED_BLINK_SPEED 0x05
@@ -484,6 +499,8 @@
#define RTSX_SD30_DRIVE_SEL_1V8 0x03
#define RTSX_SD30_DRIVE_SEL_MASK 0x07
+#define RTSX_DUMMY_REG 0xFE90
+
#define RTSX_SG_INT 0x04
#define RTSX_SG_END 0x02
#define RTSX_SG_VALID 0x01
@@ -492,4 +509,9 @@
#define RTSX_SG_TRANS_DATA (0x02 << 4)
#define RTSX_SG_LINK_DESC (0x03 << 4)
+#define RTSX_IC_VERSION_A 0x00
+#define RTSX_IC_VERSION_B 0x01
+#define RTSX_IC_VERSION_C 0x02
+#define RTSX_IC_VERSION_D 0x03
+
#endif
diff --git a/sys/dev/ic/rtsxvar.h b/sys/dev/ic/rtsxvar.h
index 814522d9c25..d94d264e8dd 100644
--- a/sys/dev/ic/rtsxvar.h
+++ b/sys/dev/ic/rtsxvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtsxvar.h,v 1.1 2012/11/29 23:36:34 stsp Exp $ */
+/* $OpenBSD: rtsxvar.h,v 1.2 2013/11/06 13:51:02 stsp Exp $ */
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
@@ -41,12 +41,15 @@ struct rtsx_softc {
/* Host controller functions called by the attachment driver. */
int rtsx_attach(struct rtsx_softc *, bus_space_tag_t,
- bus_space_handle_t, bus_size_t, bus_dma_tag_t);
+ bus_space_handle_t, bus_size_t, bus_dma_tag_t, int);
int rtsx_activate(struct device *, int);
int rtsx_intr(void *);
/* flag values */
#define RTSX_F_CARD_PRESENT 0x01
#define RTSX_F_SDIO_SUPPORT 0x02
+#define RTSX_F_5209 0x04
+#define RTSX_F_5229 0x08
+#define RTSX_F_5229_TYPE_C 0x10
#endif
diff --git a/sys/dev/pci/rtsx_pci.c b/sys/dev/pci/rtsx_pci.c
index b7cb64a79d8..ca0ffcf4e7c 100644
--- a/sys/dev/pci/rtsx_pci.c
+++ b/sys/dev/pci/rtsx_pci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtsx_pci.c,v 1.3 2013/01/05 15:42:44 stsp Exp $ */
+/* $OpenBSD: rtsx_pci.c,v 1.4 2013/11/06 13:51:02 stsp Exp $ */
/*
* Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
@@ -53,9 +53,12 @@ rtsx_pci_match(struct device *parent, void *match, void *aux)
* devices advertise a SYSTEM/SDHC class in addition to the UNDEFINED
* device class. Let sdhc(4) handle the SYSTEM/SDHC ones.
*/
- if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_REALTEK &&
- PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_REALTEK_RTS5209 &&
- PCI_CLASS(pa->pa_class) == PCI_CLASS_UNDEFINED)
+ if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_REALTEK ||
+ PCI_CLASS(pa->pa_class) != PCI_CLASS_UNDEFINED)
+ return 0;
+
+ if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_REALTEK_RTS5209 ||
+ PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_REALTEK_RTS5229)
return 1;
return 0;
@@ -71,6 +74,7 @@ rtsx_pci_attach(struct device *parent, struct device *self, void *aux)
bus_space_tag_t iot;
bus_space_handle_t ioh;
bus_size_t size;
+ int flags;
if ((pci_conf_read(pa->pa_pc, pa->pa_tag, RTSX_CFG_PCI)
& RTSX_CFG_ASIC) != 0) {
@@ -106,6 +110,11 @@ rtsx_pci_attach(struct device *parent, struct device *self, void *aux)
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)
+ if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_REALTEK_RTS5209)
+ flags = RTSX_F_5209;
+ else
+ flags = RTSX_F_5229;
+
+ if (rtsx_attach(&sc->sc, iot, ioh, size, pa->pa_dmat, flags) != 0)
printf("%s: can't initialize chip\n", sc->sc.sc_dev.dv_xname);
}