
Hi Anup,
On Wed, Jun 19, 2019 at 4:26 PM Anup Patel Anup.Patel@wdc.com wrote:
The SiFive MACB ethernet has a custom TX_CLK_SEL register to select different TX clock for 1000mbps vs 10/100mbps.
This patch adds SiFive MACB compatible string and extends the MACB ethernet driver to change TX clock using TX_CLK_SEL register for SiFive MACB.
Signed-off-by: Anup Patel anup.patel@wdc.com
drivers/net/macb.c | 38 +++++++++++++++++++++++++++----------- drivers/net/macb.h | 1 + 2 files changed, 28 insertions(+), 11 deletions(-)
diff --git a/drivers/net/macb.c b/drivers/net/macb.c index c5560a7111..31f4d71793 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -107,6 +107,7 @@ struct macb_device { unsigned int tx_tail; unsigned int next_rx_tail; bool wrapped;
bool is_sifive_macb; void *rx_buffer; void *tx_buffer;
@@ -498,18 +499,11 @@ static int macb_phy_find(struct macb_device *macb, const char *name) int __weak macb_linkspd_cb(struct udevice *dev, unsigned int speed) { #ifdef CONFIG_CLK
struct macb_device *macb = dev_get_priv(dev); struct clk tx_clk; ulong rate; int ret;
/*
* "tx_clk" is an optional clock source for MACB.
* Ignore if it does not exist in DT.
*/
ret = clk_get_by_name(dev, "tx_clk", &tx_clk);
if (ret)
return 0;
switch (speed) { case _10BASET: rate = 2500000; /* 2.5 MHz */
@@ -525,10 +519,29 @@ int __weak macb_linkspd_cb(struct udevice *dev, unsigned int speed) return 0; }
if (tx_clk.dev) {
ret = clk_set_rate(&tx_clk, rate);
if (macb->is_sifive_macb) {
/*
* GEMGXL TX clock operation mode:
*
* 0 = GMII mode. Use 125 MHz gemgxlclk from PRCI in TX logic
* and output clock on GMII output signal GTX_CLK
* 1 = MII mode. Use MII input signal TX_CLK in TX logic
*/
macb_writel(macb, SIFIVE_TX_CLK_SEL, rate != 125000000);
} else {
/*
* "tx_clk" is an optional clock source for MACB.
* Ignore if it does not exist in DT.
*/
ret = clk_get_by_name(dev, "tx_clk", &tx_clk); if (ret)
return ret;
return 0;
if (tx_clk.dev) {
ret = clk_set_rate(&tx_clk, rate);
if (ret)
return ret;
} }
#endif
@@ -1147,6 +1160,8 @@ static int macb_eth_probe(struct udevice *dev) const char *phy_mode; __maybe_unused int ret;
macb->is_sifive_macb = device_is_compatible(dev, "sifive,fu540-macb");
phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode", NULL); if (phy_mode)
@@ -1225,6 +1240,7 @@ static const struct udevice_id macb_eth_ids[] = { { .compatible = "atmel,sama5d3-gem" }, { .compatible = "atmel,sama5d4-gem" }, { .compatible = "cdns,zynq-gem" },
{ .compatible = "sifive,fu540-macb" }, { }
};
diff --git a/drivers/net/macb.h b/drivers/net/macb.h index 3cc27f8560..c3903010df 100644 --- a/drivers/net/macb.h +++ b/drivers/net/macb.h @@ -57,6 +57,7 @@ #define MACB_USRIO 0x00c0 #define MACB_WOL 0x00c4 #define MACB_MID 0x00fc +#define MACB_SIFIVE_TX_CLK_SEL 0x10000
The Linux SiFive macb device bindings says: "For "sifive,fu540-macb", second range is required to specify the address and length of the registers for GEMGXL Management block.". So in order to really keep sync with Linux driver, a second reg needs to be parsed from DT.
Regards, Bin