NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/54372: Patch for RTSX 5249 support, fix RTSX
>Number: 54372
>Category: kern
>Synopsis: Patch for RTSX 5249 support, fix RTSX
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Fri Jul 12 07:20:00 +0000 2019
>Originator: Philippe Michaud-Boudreault
>Release: 7.2 -> Current
>Organization:
n/a
>Environment:
>Description:
Hi, I want to submit this patch for the `rtsx` driver.
It adds support for the RTS5249 and also fixes an issue where the DMA transfers were completely non-functional, so I disabled them in favour of using ping-pong buffers.
>How-To-Repeat:
>Fix:
diff --git a/sys/dev/ic/rtsx.c b/sys/dev/ic/rtsx.c
index c3fe30a6493b..675395c48206 100644
--- a/sys/dev/ic/rtsx.c
+++ b/sys/dev/ic/rtsx.c
@@ -145,8 +145,10 @@ static int rtsx_write_ppbuf(struct rtsx_softc *, struct sdmmc_command *,
uint32_t *);
static int rtsx_exec_short_xfer(struct rtsx_softc *,
struct sdmmc_command *, uint32_t *, uint8_t);
+static int rtsx_xfer_exec(struct rtsx_softc *, bus_dmamap_t, int);
static int rtsx_xfer(struct rtsx_softc *, struct sdmmc_command *,
uint32_t *);
+static int rtsx_xfer_bounce(struct rtsx_softc *, struct sdmmc_command *);
static void rtsx_card_insert(struct rtsx_softc *);
static void rtsx_card_eject(struct rtsx_softc *);
static int rtsx_led_enable(struct rtsx_softc *);
@@ -224,7 +226,10 @@ rtsx_attach(struct rtsx_softc *sc, bus_space_tag_t iot,
RTSX_DMA_MAX_SEGSIZE, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW,
&sc->sc_dmap_cmd) != 0)
goto error;
-
+ if (bus_dmamap_create(sc->sc_dmat, RTSX_DMA_DATA_BUFSIZE, 1,
+ RTSX_DMA_MAX_SEGSIZE, 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW,
+ &sc->sc_dmap_data) != 0)
+ goto error;
/*
* Attach the generic SD/MMC bus driver. (The bus driver must
* not invoke any chipset functions before it is attached.)
@@ -237,7 +242,7 @@ rtsx_attach(struct rtsx_softc *sc, bus_space_tag_t iot,
saa.saa_dmat = sc->sc_dmat;
saa.saa_clkmin = SDMMC_SDCLK_400K;
saa.saa_clkmax = 25000;
- saa.saa_caps = SMC_CAPS_DMA|SMC_CAPS_4BIT_MODE;
+ saa.saa_caps = /*SMC_CAPS_SINGLE_ONLY|*/SMC_CAPS_4BIT_MODE;
sc->sc_sdmmc = config_found(sc->sc_dev, &saa, NULL);
if (sc->sc_sdmmc == NULL)
@@ -276,6 +281,7 @@ rtsx_detach(struct rtsx_softc *sc, int flags)
rtsx_soft_reset(sc);
}
+ bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmap_data);
bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmap_cmd);
cv_destroy(&sc->sc_intr_cv);
mutex_destroy(&sc->sc_intr_mtx);
@@ -378,6 +384,19 @@ rtsx_init(struct rtsx_softc *sc, int attaching)
error = rtsx_write_phy(sc, 0x00, 0xB966);
else if (RTSX_IS_RTS5227(sc) || RTSX_IS_RTS5229(sc))
error = rtsx_write_phy(sc, 0x00, 0xBA42);
+ else if (RTSX_IS_RTS5249(sc)) {
+ RTSX_WRITE(sc, 0xFF46, 0x00);
+ delay(1000);
+ error = rtsx_write_phy(sc, 0x19, 0xFE6C);
+ error|= rtsx_write_phy(sc, 0x0A, 0x05C0);
+ error|= rtsx_write_phy(sc, 0x00, 0xBA43);
+ error|= rtsx_write_phy(sc, 0x03, 0xC152);
+ error|= rtsx_write_phy(sc, 0x1E, 0x78EB);
+ error|= rtsx_write_phy(sc, 0x05, 0x4600);
+ error|= rtsx_write_phy(sc, 0x02, 0x041F);
+ error|= rtsx_write_phy(sc, 0x1D, 0x0824);
+ error|= rtsx_write_phy(sc, 0x08, 0x4FE4);
+ }
else
error = 0;
if (error) {
@@ -434,7 +453,26 @@ rtsx_init(struct rtsx_softc *sc, int attaching)
RTSX_BITOP(sc, RTSX_EFUSE_CONTENT, 0xe0, 0x80);
if (RTSX_IS_RTL8411B(sc))
RTSX_WRITE(sc, RTSX_FUNC_FORCE_CTL, 0x00);
- }
+ } else if (RTSX_IS_RTS5249(sc)) {
+ /* Rest L1SUB Config */
+ RTSX_WRITE(sc, 0xFE8F, 0x00);
+ /* Configure GPIO as output */
+ RTSX_WRITE(sc, RTSX_GPIO_CTL, 0x02);
+ /* Reset ASPM state to default value */
+ RTSX_WRITE(sc, 0xFE57, 0x00);
+ /* Switch LDO3318 source from DV33 to card_3v3 */
+ RTSX_WRITE(sc, RTSX_LDO_PWR_SEL, 0x00);
+ RTSX_WRITE(sc, RTSX_LDO_PWR_SEL, 0x01);
+ /* Set default OLT blink period. */
+ RTSX_WRITE(sc, RTSX_OLT_LED_CTL, 0x02);
+
+ /* Configure driving for 3V3. */
+ RTSX_WRITE(sc, 0xFD5A, 0x96);
+ RTSX_WRITE(sc, 0xFD5E, 0x96);
+ RTSX_WRITE(sc, 0xFD5F, 0x96);
+
+ RTSX_WRITE(sc, RTSX_PETXCFG, 0x80);
+ }
return 0;
}
@@ -447,7 +485,7 @@ 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);
- } else if (RTSX_IS_RTS5227(sc) || RTSX_IS_RTS5229(sc)) {
+ } else if (RTSX_IS_RTS5227(sc) || RTSX_IS_RTS5229(sc) || RTSX_IS_RTS5249(sc)) {
RTSX_SET(sc, RTSX_GPIO_CTL, RTSX_GPIO_LED_ON);
RTSX_SET(sc, RTSX_OLT_LED_CTL, RTSX_OLT_LED_AUTOBLINK);
} else if (RTSX_IS_RTL8402(sc)
@@ -468,7 +506,7 @@ rtsx_led_disable(struct rtsx_softc *sc)
if (RTSX_IS_RTS5209(sc)) {
RTSX_CLR(sc, RTSX_CARD_AUTO_BLINK, RTSX_LED_BLINK_EN);
RTSX_WRITE(sc, RTSX_CARD_GPIO, RTSX_CARD_GPIO_LED_OFF);
- } else if (RTSX_IS_RTS5227(sc) || RTSX_IS_RTS5229(sc)) {
+ } else if (RTSX_IS_RTS5227(sc) || RTSX_IS_RTS5229(sc) || RTSX_IS_RTS5249(sc)) {
RTSX_CLR(sc, RTSX_OLT_LED_CTL, RTSX_OLT_LED_AUTOBLINK);
RTSX_CLR(sc, RTSX_GPIO_CTL, RTSX_GPIO_LED_ON);
} else if (RTSX_IS_RTL8402(sc)
@@ -572,7 +610,10 @@ rtsx_bus_power_off(struct rtsx_softc *sc)
RTSX_BPP_POWER_OFF);
RTSX_BITOP(sc, RTSX_LDO_CTL, RTSX_BPP_LDO_POWB,
RTSX_BPP_LDO_SUSPEND);
- }
+ } else if (RTSX_IS_RTS5249(sc)) {
+ RTSX_CLR(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_VCC1 |
+ RTSX_LDO3318_VCC2);
+ }
RTSX_SET(sc, RTSX_CARD_PWR_CTL, RTSX_SD_PWR_OFF);
RTSX_CLR(sc, RTSX_CARD_PWR_CTL, RTSX_PMOS_STRG_800mA);
@@ -602,7 +643,12 @@ rtsx_bus_power_off(struct rtsx_softc *sc)
RTSX_WRITE(sc, RTSX_CARD_PULL_CTL5, 0x55);
RTSX_WRITE(sc, RTSX_CARD_PULL_CTL6, 0x15);
}
- }
+ } else if (RTSX_IS_RTS5249(sc)) {
+ RTSX_WRITE(sc, RTSX_CARD_PULL_CTL1, 0x66);
+ RTSX_WRITE(sc, RTSX_CARD_PULL_CTL2, 0x55);
+ RTSX_WRITE(sc, RTSX_CARD_PULL_CTL3, 0xD5);
+ RTSX_WRITE(sc, RTSX_CARD_PULL_CTL4, 0x55);
+ }
return 0;
}
@@ -646,7 +692,12 @@ rtsx_bus_power_on(struct rtsx_softc *sc)
RTSX_WRITE(sc, RTSX_CARD_PULL_CTL5, 0x59);
RTSX_WRITE(sc, RTSX_CARD_PULL_CTL6, 0x15);
}
- }
+ } else if (RTSX_IS_RTS5249(sc)) {
+ RTSX_WRITE(sc, RTSX_CARD_PULL_CTL1, 0x66);
+ RTSX_WRITE(sc, RTSX_CARD_PULL_CTL2, 0xAA);
+ RTSX_WRITE(sc, RTSX_CARD_PULL_CTL3, 0xE9);
+ RTSX_WRITE(sc, RTSX_CARD_PULL_CTL4, 0xAA);
+ }
/*
* To avoid a current peak, enable card power in two phases with a
@@ -687,7 +738,17 @@ rtsx_bus_power_on(struct rtsx_softc *sc)
RTSX_BPP_POWER_ON);
RTSX_BITOP(sc, RTSX_LDO_CTL, RTSX_BPP_LDO_POWB,
RTSX_BPP_LDO_ON);
- }
+ } else if (RTSX_IS_RTS5249(sc)) {
+ /* Partial power. */
+ RTSX_SET(sc, RTSX_CARD_PWR_CTL, RTSX_VCC_PARTIAL_PWR_ON);
+ RTSX_SET(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_VCC1);
+
+ delay(5000);
+
+ /* Full power. */
+ RTSX_CLR(sc, RTSX_CARD_PWR_CTL, RTSX_SD_PWR_OFF);
+ RTSX_SET(sc, RTSX_PWR_GATE_CTRL, RTSX_LDO3318_VCC1 | RTSX_LDO3318_VCC2);
+ }
/* Enable SD card output. */
RTSX_WRITE(sc, RTSX_CARD_OE, RTSX_SD_OUTPUT_EN);
@@ -1358,6 +1419,21 @@ ret:
return error;
}
+static int
+rtsx_xfer_exec(struct rtsx_softc *sc, bus_dmamap_t dmap, int dmaflags)
+{
+ mutex_enter(&sc->sc_host_mtx);
+
+ /* Tell the chip where the data buffer is and run the transfer. */
+ WRITE4(sc, RTSX_HDBAR, dmap->dm_segs[0].ds_addr);
+ WRITE4(sc, RTSX_HDBCTLR, dmaflags);
+
+ mutex_exit(&sc->sc_host_mtx);
+
+ /* Wait for completion. */
+ return rtsx_wait_intr(sc, RTSX_TRANS_OK_INT, 10*hz);
+}
+
static int
rtsx_xfer(struct rtsx_softc *sc, struct sdmmc_command *cmd, uint32_t *cmdbuf)
{
@@ -1440,22 +1516,82 @@ rtsx_xfer(struct rtsx_softc *sc, struct sdmmc_command *cmd, uint32_t *cmdbuf)
if (error)
goto ret;
- mutex_enter(&sc->sc_host_mtx);
-
- /* Tell the chip where the data buffer is and run the transfer. */
- WRITE4(sc, RTSX_HDBAR, cmd->c_dmamap->dm_segs[0].ds_addr);
- WRITE4(sc, RTSX_HDBCTLR, RTSX_TRIG_DMA | (read ? RTSX_DMA_READ : 0) |
- (cmd->c_dmamap->dm_segs[0].ds_len & 0x00ffffff));
-
- mutex_exit(&sc->sc_host_mtx);
+ if (cmd->c_dmamap)
+ /*error = rtsx_xfer_adma(sc, cmd)*/ error = 0;
+ else
+ error = rtsx_xfer_bounce(sc, cmd);
- /* Wait for completion. */
- error = rtsx_wait_intr(sc, RTSX_TRANS_OK_INT, 10*hz);
ret:
DPRINTF(3,("%s: xfer done, error=%d\n", DEVNAME(sc), error));
return error;
}
+static int
+rtsx_xfer_bounce(struct rtsx_softc *sc, struct sdmmc_command *cmd)
+{
+ void *datakvap;
+ bus_dma_segment_t segs;
+ int rsegs, error;
+ int read = ISSET(cmd->c_flags, SCF_CMD_READ);
+
+ /* Allocate and map DMA bounce buffer for data transfer. */
+ error = bus_dmamem_alloc(sc->sc_dmat, cmd->c_datalen, 0, 0, &segs, 1,
+ &rsegs, BUS_DMA_WAITOK);
+ if (error) {
+ DPRINTF(3, ("%s: could not allocate %d bytes\n",
+ DEVNAME(sc), cmd->c_datalen));
+ return error;
+ }
+ error = bus_dmamem_map(sc->sc_dmat, &segs, rsegs, cmd->c_datalen,
+ &datakvap, BUS_DMA_WAITOK|BUS_DMA_COHERENT);
+ if (error) {
+ DPRINTF(3, ("%s: could not map data buffer\n", DEVNAME(sc)));
+ goto free_databuf;
+ }
+
+ /* If this is a write, copy data from sdmmc-provided buffer. */
+ if (!read)
+ memcpy(datakvap, cmd->c_data, cmd->c_datalen);
+
+ /* Load the data buffer and sync it. */
+ error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmap_data, datakvap,
+ cmd->c_datalen, NULL, BUS_DMA_WAITOK);
+ if (error) {
+ DPRINTF(3, ("%s: could not load DMA map\n", DEVNAME(sc)));
+ goto unmap_databuf;
+ }
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_dmap_data, 0, cmd->c_datalen,
+ BUS_DMASYNC_PREREAD);
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_dmap_data, 0, cmd->c_datalen,
+ BUS_DMASYNC_PREWRITE);
+
+ error = rtsx_xfer_exec(sc, sc->sc_dmap_data,
+ RTSX_TRIG_DMA | (read ? RTSX_DMA_READ : 0) |
+ (cmd->c_datalen & 0x00ffffff));
+ if (error)
+ goto unload_databuf;
+
+ /* Sync and unload data DMA buffer. */
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_dmap_data, 0, cmd->c_datalen,
+ BUS_DMASYNC_POSTREAD);
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_dmap_data, 0, cmd->c_datalen,
+ BUS_DMASYNC_POSTWRITE);
+
+unload_databuf:
+ bus_dmamap_unload(sc->sc_dmat, sc->sc_dmap_data);
+
+ /* If this is a read, copy data into sdmmc-provided buffer. */
+ if (error == 0 && read)
+ memcpy(cmd->c_data, datakvap, cmd->c_datalen);
+
+ /* Free DMA data buffer. */
+unmap_databuf:
+ bus_dmamem_unmap(sc->sc_dmat, datakvap, cmd->c_datalen);
+free_databuf:
+ bus_dmamem_free(sc->sc_dmat, &segs, rsegs);
+ return error;
+}
+
static void
rtsx_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
{
diff --git a/sys/dev/ic/rtsxreg.h b/sys/dev/ic/rtsxreg.h
index 447c39549ba5..ad75399554eb 100644
--- a/sys/dev/ic/rtsxreg.h
+++ b/sys/dev/ic/rtsxreg.h
@@ -82,6 +82,7 @@
#define RTSX_CARD_PWR_CTL 0xFD50
#define RTSX_SD_PWR_ON 0x00
#define RTSX_SD_PARTIAL_PWR_ON 0x01
+#define RTSX_VCC_PARTIAL_PWR_ON 0x02
#define RTSX_SD_PWR_OFF 0x03
#define RTSX_SD_PWR_MASK 0x03
#define RTSX_PMOS_STRG_MASK 0x10
diff --git a/sys/dev/ic/rtsxvar.h b/sys/dev/ic/rtsxvar.h
index 0d8acb2daeeb..74d296caf8f1 100644
--- a/sys/dev/ic/rtsxvar.h
+++ b/sys/dev/ic/rtsxvar.h
@@ -40,6 +40,7 @@ struct rtsx_softc {
bus_size_t sc_iosize;
bus_dma_tag_t sc_dmat; /* DMA tag from attachment driver */
bus_dmamap_t sc_dmap_cmd; /* DMA map for command transfer */
+ bus_dmamap_t sc_dmap_data; /* DMA map for data transfer */
struct kmutex sc_host_mtx;
struct kmutex sc_intr_mtx;
@@ -61,6 +62,7 @@ struct rtsx_softc {
#define RTSX_F_8411 __BIT(7)
#define RTSX_F_8411B __BIT(8)
#define RTSX_F_8411B_QFN48 __BIT(9)
+#define RTSX_F_5249 __BIT(11)
};
#define RTSX_IS_RTS5209(sc) (((sc)->sc_flags & RTSX_F_5209) == RTSX_F_5209)
@@ -69,6 +71,7 @@ struct rtsx_softc {
#define RTSX_IS_RTS5229_TYPE_C(sc) \
(((sc)->sc_flags & (RTSX_F_5229|RTSX_F_5229_TYPE_C)) == \
(RTSX_F_5229|RTSX_F_5229_TYPE_C))
+#define RTSX_IS_RTS5249(sc) (((sc)->sc_flags & RTSX_F_5249) == RTSX_F_5249)
#define RTSX_IS_RTL8402(sc) (((sc)->sc_flags & RTSX_F_8402) == RTSX_F_8402)
#define RTSX_IS_RTL8411(sc) (((sc)->sc_flags & RTSX_F_8411) == RTSX_F_8411)
#define RTSX_IS_RTL8411B(sc) \
diff --git a/sys/dev/pci/rtsx_pci.c b/sys/dev/pci/rtsx_pci.c
index a856dc1ba167..6ae2f6431eef 100644
--- a/sys/dev/pci/rtsx_pci.c
+++ b/sys/dev/pci/rtsx_pci.c
@@ -76,6 +76,7 @@ rtsx_pci_match(device_t parent, cfdata_t cf, void *aux)
case PCI_PRODUCT_REALTEK_RTS5209:
case PCI_PRODUCT_REALTEK_RTS5227:
case PCI_PRODUCT_REALTEK_RTS5229:
+ case PCI_PRODUCT_REALTEK_RTS5249:
case PCI_PRODUCT_REALTEK_RTL8402:
case PCI_PRODUCT_REALTEK_RTL8411:
case PCI_PRODUCT_REALTEK_RTL8411B:
@@ -147,6 +148,9 @@ rtsx_pci_attach(device_t parent, device_t self, void *aux)
case PCI_PRODUCT_REALTEK_RTS5229:
flags = RTSX_F_5229;
break;
+ case PCI_PRODUCT_REALTEK_RTS5249:
+ flags = RTSX_F_5249;
+ break;
case PCI_PRODUCT_REALTEK_RTL8402:
flags = RTSX_F_8402;
break;
Home |
Main Index |
Thread Index |
Old Index