Page MenuHomeFreeBSD

D31148.diff
No OneTemporary

D31148.diff

Index: sys/dev/cadence/if_cgem.c
===================================================================
--- sys/dev/cadence/if_cgem.c
+++ sys/dev/cadence/if_cgem.c
@@ -1516,6 +1516,145 @@
sc->mii_media_active = mii->mii_media_active;
}
+#ifdef EXT_RESOURCES
+/*
+ * Clock node driver for ethernet transmit clock in SiFive FU540 and FU740
+ * SoCs.
+ */
+struct sifive_tx_clk_sc {
+ struct resource *mem_res;
+ clk_t pclk;
+ uint64_t freq;
+};
+
+#define TX_CLK_ID 0
+#define TX_CLK_NAME "tx_clk"
+
+static int
+cgem_sifive_tx_clk_init(struct clknode *clk, device_t dev)
+{
+ int rid;
+ struct sifive_tx_clk_sc *sc = clknode_get_softc(clk);
+
+ /* Get memory resource of GEMGXL Management block. */
+ rid = 1;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "could not allocate memory resources.\n");
+ return (ENOMEM);
+ }
+
+ return (0);
+}
+
+static int
+cgem_sifive_tx_clk_recalc_freq(struct clknode *clk, uint64_t *freq)
+{
+ struct sifive_tx_clk_sc *sc = clknode_get_softc(clk);
+
+ *freq = sc->freq;
+
+ return (0);
+}
+
+static int
+cgem_sifive_tx_clk_set_freq(struct clknode *clk, uint64_t fin, uint64_t *fout,
+ int flags, int *done)
+{
+ struct sifive_tx_clk_sc *sc = clknode_get_softc(clk);
+
+ switch (*fout) {
+ case 2500000:
+ case 25000000:
+ WR4(sc, CGEM_MGMT_TX_CLK_SEL, CGEM_MGMT_TX_CLK_SEL_MII);
+ break;
+ case 125000000:
+ WR4(sc, CGEM_MGMT_TX_CLK_SEL, CGEM_MGMT_TX_CLK_SEL_GMII);
+ break;
+ default:
+ printf("%s: invalid frequency: %lu\n", __func__, *fout);
+ return (EINVAL);
+ }
+
+ sc->freq = *fout;
+ *done = 1;
+
+ return (0);
+}
+
+static clknode_method_t sifive_tx_clk_clknode_methods[] = {
+ CLKNODEMETHOD(clknode_init, cgem_sifive_tx_clk_init),
+ CLKNODEMETHOD(clknode_recalc_freq, cgem_sifive_tx_clk_recalc_freq),
+ CLKNODEMETHOD(clknode_set_freq, cgem_sifive_tx_clk_set_freq),
+
+ CLKNODEMETHOD_END
+};
+
+DEFINE_CLASS_1(sifive_tx_clk_clknode, sifive_tx_clk_clknode_class,
+ sifive_tx_clk_clknode_methods, sizeof(struct sifive_tx_clk_sc),
+ clknode_class);
+
+static int
+cgem_sifive_clk_setup(struct cgem_softc *sc)
+{
+ device_t dev = sc->dev;
+ struct clkdom *clkdom;
+ struct clknode_init_def clkdef;
+ struct clknode *clk;
+ struct sifive_tx_clk_sc *csc;
+
+ clkdom_xlock(NULL);
+ clkdom = clkdom_get_by_dev(dev);
+ clkdom_unlock(NULL);
+ if (clkdom == NULL) {
+ clkdom = clkdom_create(dev);
+ if (clkdom == NULL) {
+ device_printf(dev, "could not create clock domain.\n");
+ return (-1);
+ }
+
+ memset(&clkdef, 0, sizeof(clkdef));
+ clkdef.id = TX_CLK_ID;
+ clkdef.name = TX_CLK_NAME;
+ clkdef.flags = CLK_NODE_STATIC_STRINGS;
+
+ clk = clknode_create(clkdom, &sifive_tx_clk_clknode_class,
+ &clkdef);
+ if (clk == NULL) {
+ device_printf(dev, "could not create clock node.\n");
+ return (-1);
+ }
+
+ clknode_register(clkdom, clk);
+
+ if (clkdom_finit(clkdom)) {
+ device_printf(dev,
+ "could not finalise clock domain.\n");
+ return (-1);
+ }
+
+ /* Retrieve and enable GEMGXLPLL. */
+ csc = clknode_get_softc(clk);
+ if (clk_get_by_ofw_name(dev, 0, "pclk", &csc->pclk) != 0) {
+ device_printf(dev, "could not retrieve pclk.\n");
+ return (-1);
+ }
+ if (clk_enable(csc->pclk) != 0) {
+ device_printf(dev, "could not enable pclk.\n");
+ return (-1);
+ }
+ }
+
+ if (clk_get_by_id(dev, clkdom, TX_CLK_ID, &sc->ref_clk) != 0) {
+ device_printf(dev, "could not retrieve clock form domain.\n");
+ return (-1);
+ }
+
+ return (0);
+}
+#endif /* EXT_RESOURCES */
+
static void
cgem_add_sysctls(device_t dev)
{
@@ -1764,7 +1903,7 @@
else if (clk_enable(sc->ref_clk) != 0)
device_printf(dev, "could not enable clock.\n");
} else if (hwtype == HWTYPE_SIFIVE) {
- if (clk_get_by_ofw_name(dev, 0, "pclk", &sc->ref_clk) != 0)
+ if (cgem_sifive_clk_setup(sc) != 0)
device_printf(dev,
"could not retrieve reference clock.\n");
else if (clk_enable(sc->ref_clk) != 0)
Index: sys/dev/cadence/if_cgem_hw.h
===================================================================
--- sys/dev/cadence/if_cgem_hw.h
+++ sys/dev/cadence/if_cgem_hw.h
@@ -443,4 +443,17 @@
#endif
};
+/*
+ * GEMGXL Management Control Registers for SiFive SoCs:
+ *
+ * Reference: SiFive FU740-C000 Manual v1p2, section 22.2.
+ */
+#define CGEM_MGMT_TX_CLK_SEL 0x000
+#define CGEM_MGMT_TX_CLK_SEL_GMII 0x0
+#define CGEM_MGMT_TX_CLK_SEL_MII 0x1
+#define CGEM_MGMT_CTRLSTAT_SPEED_MODE 0x020
+#define CGEM_MGMT_SPEED_MODE_10 0x0
+#define CGEM_MGMT_SPEED_MODE_100 0x1
+#define CGEM_MGMT_SPEED_MODE_1000 0x3
+
#endif /* _IF_CGEM_HW_H_ */

File Metadata

Mime Type
text/plain
Expires
Thu, May 1, 8:05 AM (12 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17877036
Default Alt Text
D31148.diff (4 KB)

Event Timeline