Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F115912108
D31148.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D31148.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D31148: cgem: fix media changes on SiFive platforms.
Attached
Detach File
Event Timeline
Log In to Comment