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