diff options
-rw-r--r-- | share/man/man4/rtsx.4 | 7 | ||||
-rw-r--r-- | sys/dev/ic/rtsx.c | 115 | ||||
-rw-r--r-- | sys/dev/ic/rtsxreg.h | 34 | ||||
-rw-r--r-- | sys/dev/ic/rtsxvar.h | 7 | ||||
-rw-r--r-- | sys/dev/pci/rtsx_pci.c | 19 |
5 files changed, 149 insertions, 33 deletions
diff --git a/share/man/man4/rtsx.4 b/share/man/man4/rtsx.4 index f3ed6be7a66..8c1eb73e579 100644 --- a/share/man/man4/rtsx.4 +++ b/share/man/man4/rtsx.4 @@ -1,9 +1,9 @@ -.\" $OpenBSD: rtsx.4,v 1.3 2013/07/16 16:05:49 schwarze Exp $ +.\" $OpenBSD: rtsx.4,v 1.4 2013/11/06 13:51:02 stsp Exp $ .\" .\" Theo de Raadt, 2006. Public Domain. .\" Stefan Sperling, 2012. Public Domain. .\" -.Dd $Mdocdate: July 16 2013 $ +.Dd $Mdocdate: November 6 2013 $ .Dt RTSX 4 .Os .Sh NAME @@ -15,7 +15,8 @@ .Sh DESCRIPTION The .Nm -driver provides support for the Realtek RTS5209 SD card reader. +driver provides support for the Realtek RTS5209 and RTS5229 SD card +readers. .Pp The .Xr sdmmc 4 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); } |