git: 4c52dde5bda0 - main - if_cgem: Rewrite clock part

From: Emmanuel Vadot <manu_at_FreeBSD.org>
Date: Mon, 18 Sep 2023 13:24:55 UTC
The branch main has been updated by manu:

URL: https://cgit.FreeBSD.org/src/commit/?id=4c52dde5bda099936d43820da84e569dccc6f475

commit 4c52dde5bda099936d43820da84e569dccc6f475
Author:     Emmanuel Vadot <manu@FreeBSD.org>
AuthorDate: 2023-09-14 08:57:19 +0000
Commit:     Emmanuel Vadot <manu@FreeBSD.org>
CommitDate: 2023-09-18 13:24:27 +0000

    if_cgem: Rewrite clock part
    
     - pclk and hclk are mandatory so always try to get them.
       Don't make it fatal if it fails as some platform (like Zynq) don't
       have a proper clock driver.
     - Always use pclk for the reference clock.
     - Try to get all the possible clocks and enable them.
    
    Reviewed-by:    mhorne
    Tested-by:      Milan Obuch <bsd@dino.sk>
    Differential Revision:  https://reviews.freebsd.org/D41857
    Sponsored by:   Beckhoff Automation GmbH & Co. KG
---
 sys/dev/cadence/if_cgem.c | 118 +++++++++++++++++++++++++++++++++-------------
 1 file changed, 86 insertions(+), 32 deletions(-)

diff --git a/sys/dev/cadence/if_cgem.c b/sys/dev/cadence/if_cgem.c
index 43e35b2bf849..6e4a62f6e5ee 100644
--- a/sys/dev/cadence/if_cgem.c
+++ b/sys/dev/cadence/if_cgem.c
@@ -102,17 +102,15 @@
 #define HWQUIRK_NONE		0
 #define HWQUIRK_NEEDNULLQS	1
 #define HWQUIRK_RXHANGWAR	2
-#define HWQUIRK_TXCLK		4
-#define HWQUIRK_PCLK		8
 
 static struct ofw_compat_data compat_data[] = {
-	{ "cdns,zynq-gem",		HWQUIRK_RXHANGWAR | HWQUIRK_TXCLK }, /* Deprecated */
-	{ "cdns,zynqmp-gem",		HWQUIRK_NEEDNULLQS | HWQUIRK_TXCLK }, /* Deprecated */
-	{ "xlnx,zynq-gem",		HWQUIRK_RXHANGWAR | HWQUIRK_TXCLK },
-	{ "xlnx,zynqmp-gem",		HWQUIRK_NEEDNULLQS | HWQUIRK_TXCLK },
-	{ "microchip,mpfs-mss-gem",	HWQUIRK_NEEDNULLQS | HWQUIRK_TXCLK },
-	{ "sifive,fu540-c000-gem",	HWQUIRK_PCLK },
-	{ "sifive,fu740-c000-gem",	HWQUIRK_PCLK },
+	{ "cdns,zynq-gem",		HWQUIRK_RXHANGWAR }, /* Deprecated */
+	{ "cdns,zynqmp-gem",		HWQUIRK_NEEDNULLQS }, /* Deprecated */
+	{ "xlnx,zynq-gem",		HWQUIRK_RXHANGWAR },
+	{ "xlnx,zynqmp-gem",		HWQUIRK_NEEDNULLQS },
+	{ "microchip,mpfs-mss-gem",	HWQUIRK_NEEDNULLQS },
+	{ "sifive,fu540-c000-gem",	HWQUIRK_NONE },
+	{ "sifive,fu740-c000-gem",	HWQUIRK_NONE },
 	{ NULL,				0 }
 };
 
@@ -129,7 +127,11 @@ struct cgem_softc {
 	struct callout		tick_ch;
 	uint32_t		net_ctl_shadow;
 	uint32_t		net_cfg_shadow;
-	clk_t			ref_clk;
+	clk_t			clk_pclk;
+	clk_t			clk_hclk;
+	clk_t			clk_txclk;
+	clk_t			clk_rxclk;
+	clk_t			clk_tsuclk;
 	int			neednullqs;
 	int			phy_contype;
 
@@ -1497,9 +1499,9 @@ cgem_mediachange(struct cgem_softc *sc,	struct mii_data *mii)
 
 	WR4(sc, CGEM_NET_CFG, sc->net_cfg_shadow);
 
-	if (sc->ref_clk != NULL) {
+	if (sc->clk_pclk != NULL) {
 		CGEM_UNLOCK(sc);
-		if (clk_set_freq(sc->ref_clk, ref_clk_freq, 0))
+		if (clk_set_freq(sc->clk_pclk, ref_clk_freq, 0))
 			device_printf(sc->dev, "could not set ref clk to %d\n",
 			    ref_clk_freq);
 		CGEM_LOCK(sc);
@@ -1744,19 +1746,47 @@ cgem_attach(device_t dev)
 		sc->neednullqs = 1;
 	if ((hwquirks & HWQUIRK_RXHANGWAR) != 0)
 		sc->rxhangwar = 1;
-	if ((hwquirks & HWQUIRK_TXCLK) != 0) {
-		if (clk_get_by_ofw_name(dev, 0, "tx_clk", &sc->ref_clk) != 0)
-			device_printf(dev,
-			    "could not retrieve reference clock.\n");
-		else if (clk_enable(sc->ref_clk) != 0)
-			device_printf(dev, "could not enable clock.\n");
+	/*
+	 * Both pclk and hclk are mandatory but we don't have a proper
+	 * clock driver for Zynq so don't make it fatal if we can't
+	 * get them.
+	 */
+	if (clk_get_by_ofw_name(dev, 0, "pclk", &sc->clk_pclk) != 0)
+		device_printf(dev,
+		  "could not retrieve pclk.\n");
+	else {
+		if (clk_enable(sc->clk_pclk) != 0)
+			device_printf(dev, "could not enable pclk.\n");
+	}
+	if (clk_get_by_ofw_name(dev, 0, "hclk", &sc->clk_hclk) != 0)
+		device_printf(dev,
+		  "could not retrieve hclk.\n");
+	else {
+		if (clk_enable(sc->clk_hclk) != 0)
+			device_printf(dev, "could not enable hclk.\n");
+	}
+
+	/* Optional clocks */
+	if (clk_get_by_ofw_name(dev, 0, "tx_clk", &sc->clk_txclk) == 0) {
+		if (clk_enable(sc->clk_txclk) != 0) {
+			device_printf(dev, "could not enable tx_clk.\n");
+			err = ENXIO;
+			goto err_pclk;
+		}
+	}
+	if (clk_get_by_ofw_name(dev, 0, "rx_clk", &sc->clk_rxclk) == 0) {
+		if (clk_enable(sc->clk_rxclk) != 0) {
+			device_printf(dev, "could not enable rx_clk.\n");
+			err = ENXIO;
+			goto err_tx_clk;
+		}
 	}
-	if ((hwquirks & HWQUIRK_PCLK) != 0) {
-		if (clk_get_by_ofw_name(dev, 0, "pclk", &sc->ref_clk) != 0)
-			device_printf(dev,
-			    "could not retrieve reference clock.\n");
-		else if (clk_enable(sc->ref_clk) != 0)
-			device_printf(dev, "could not enable clock.\n");
+	if (clk_get_by_ofw_name(dev, 0, "tsu_clk", &sc->clk_tsuclk) == 0) {
+		if (clk_enable(sc->clk_tsuclk) != 0) {
+			device_printf(dev, "could not enable tsu_clk.\n");
+			err = ENXIO;
+			goto err_rx_clk;
+		}
 	}
 
 	node = ofw_bus_get_node(dev);
@@ -1768,7 +1798,8 @@ cgem_attach(device_t dev)
 	    RF_ACTIVE);
 	if (sc->mem_res == NULL) {
 		device_printf(dev, "could not allocate memory resources.\n");
-		return (ENOMEM);
+		err = ENOMEM;
+		goto err_tsu_clk;
 	}
 
 	/* Get IRQ resource. */
@@ -1824,7 +1855,7 @@ cgem_attach(device_t dev)
 	if (err) {
 		device_printf(dev, "could not set up dma mem for descs.\n");
 		cgem_detach(dev);
-		return (ENOMEM);
+		goto err;
 	}
 
 	/* Get a MAC address. */
@@ -1841,12 +1872,29 @@ cgem_attach(device_t dev)
 		device_printf(dev, "could not set interrupt handler.\n");
 		ether_ifdetach(ifp);
 		cgem_detach(dev);
-		return (err);
+		goto err;
 	}
 
 	cgem_add_sysctls(dev);
 
 	return (0);
+
+err_tsu_clk:
+	if (sc->clk_tsuclk)
+		clk_release(sc->clk_tsuclk);
+err_rx_clk:
+	if (sc->clk_rxclk)
+		clk_release(sc->clk_rxclk);
+err_tx_clk:
+	if (sc->clk_txclk)
+		clk_release(sc->clk_txclk);
+err_pclk:
+	if (sc->clk_pclk)
+		clk_release(sc->clk_pclk);
+	if (sc->clk_hclk)
+		clk_release(sc->clk_hclk);
+err:
+	return (err);
 }
 
 static int
@@ -1923,13 +1971,19 @@ cgem_detach(device_t dev)
 		sc->mbuf_dma_tag = NULL;
 	}
 
-	if (sc->ref_clk != NULL) {
-		clk_release(sc->ref_clk);
-		sc->ref_clk = NULL;
-	}
-
 	bus_generic_detach(dev);
 
+	if (sc->clk_tsuclk)
+		clk_release(sc->clk_tsuclk);
+	if (sc->clk_rxclk)
+		clk_release(sc->clk_rxclk);
+	if (sc->clk_txclk)
+		clk_release(sc->clk_txclk);
+	if (sc->clk_pclk)
+		clk_release(sc->clk_pclk);
+	if (sc->clk_hclk)
+		clk_release(sc->clk_hclk);
+
 	CGEM_LOCK_DESTROY(sc);
 
 	return (0);