123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- From 4181aa6e771dcc09b62eb3495bd09bf151b8bd9d Mon Sep 17 00:00:00 2001
- From: Yash Shah <yash.shah@sifive.com>
- Date: Tue, 18 Jun 2019 13:26:08 +0530
- Subject: [PATCH 2/6] macb: Add support for SiFive FU540-C000
- The management IP block is tightly coupled with the Cadence MACB IP
- block on the FU540, and manages many of the boundary signals from the
- MACB IP. This patch only controls the tx_clk input signal to the MACB
- IP. Future patches may add support for monitoring or controlling other
- IP boundary signals.
- Signed-off-by: Yash Shah <yash.shah@sifive.com>
- Upstream-Status: Accepted [5.3]
- ---
- drivers/net/ethernet/cadence/macb_main.c | 123 +++++++++++++++++++++++
- 1 file changed, 123 insertions(+)
- diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
- index 262a28ff81fc..111bf51a8405 100644
- --- a/drivers/net/ethernet/cadence/macb_main.c
- +++ b/drivers/net/ethernet/cadence/macb_main.c
- @@ -7,6 +7,7 @@
-
- #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
- #include <linux/clk.h>
- +#include <linux/clk-provider.h>
- #include <linux/crc32.h>
- #include <linux/module.h>
- #include <linux/moduleparam.h>
- @@ -37,6 +38,15 @@
- #include <linux/pm_runtime.h>
- #include "macb.h"
-
- +/* This structure is only used for MACB on SiFive FU540 devices */
- +struct sifive_fu540_macb_mgmt {
- + void __iomem *reg;
- + unsigned long rate;
- + struct clk_hw hw;
- +};
- +
- +static struct sifive_fu540_macb_mgmt *mgmt;
- +
- #define MACB_RX_BUFFER_SIZE 128
- #define RX_BUFFER_MULTIPLE 64 /* bytes */
-
- @@ -3943,6 +3953,116 @@ static int at91ether_init(struct platform_device *pdev)
- return 0;
- }
-
- +static unsigned long fu540_macb_tx_recalc_rate(struct clk_hw *hw,
- + unsigned long parent_rate)
- +{
- + return mgmt->rate;
- +}
- +
- +static long fu540_macb_tx_round_rate(struct clk_hw *hw, unsigned long rate,
- + unsigned long *parent_rate)
- +{
- + if (WARN_ON(rate < 2500000))
- + return 2500000;
- + else if (rate == 2500000)
- + return 2500000;
- + else if (WARN_ON(rate < 13750000))
- + return 2500000;
- + else if (WARN_ON(rate < 25000000))
- + return 25000000;
- + else if (rate == 25000000)
- + return 25000000;
- + else if (WARN_ON(rate < 75000000))
- + return 25000000;
- + else if (WARN_ON(rate < 125000000))
- + return 125000000;
- + else if (rate == 125000000)
- + return 125000000;
- +
- + WARN_ON(rate > 125000000);
- +
- + return 125000000;
- +}
- +
- +static int fu540_macb_tx_set_rate(struct clk_hw *hw, unsigned long rate,
- + unsigned long parent_rate)
- +{
- + rate = fu540_macb_tx_round_rate(hw, rate, &parent_rate);
- + if (rate != 125000000)
- + iowrite32(1, mgmt->reg);
- + else
- + iowrite32(0, mgmt->reg);
- + mgmt->rate = rate;
- +
- + return 0;
- +}
- +
- +static const struct clk_ops fu540_c000_ops = {
- + .recalc_rate = fu540_macb_tx_recalc_rate,
- + .round_rate = fu540_macb_tx_round_rate,
- + .set_rate = fu540_macb_tx_set_rate,
- +};
- +
- +static int fu540_c000_clk_init(struct platform_device *pdev, struct clk **pclk,
- + struct clk **hclk, struct clk **tx_clk,
- + struct clk **rx_clk, struct clk **tsu_clk)
- +{
- + struct clk_init_data init;
- + int err = 0;
- +
- + err = macb_clk_init(pdev, pclk, hclk, tx_clk, rx_clk, tsu_clk);
- + if (err)
- + return err;
- +
- + mgmt = devm_kzalloc(&pdev->dev, sizeof(*mgmt), GFP_KERNEL);
- + if (!mgmt)
- + return -ENOMEM;
- +
- + init.name = "sifive-gemgxl-mgmt";
- + init.ops = &fu540_c000_ops;
- + init.flags = 0;
- + init.num_parents = 0;
- +
- + mgmt->rate = 0;
- + mgmt->hw.init = &init;
- +
- + *tx_clk = clk_register(NULL, &mgmt->hw);
- + if (IS_ERR(*tx_clk))
- + return PTR_ERR(*tx_clk);
- +
- + err = clk_prepare_enable(*tx_clk);
- + if (err)
- + dev_err(&pdev->dev, "failed to enable tx_clk (%u)\n", err);
- + else
- + dev_info(&pdev->dev, "Registered clk switch '%s'\n", init.name);
- +
- + return 0;
- +}
- +
- +static int fu540_c000_init(struct platform_device *pdev)
- +{
- + struct resource *res;
- +
- + res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- + if (!res)
- + return -ENODEV;
- +
- + mgmt->reg = ioremap(res->start, resource_size(res));
- + if (!mgmt->reg)
- + return -ENOMEM;
- +
- + return macb_init(pdev);
- +}
- +
- +static const struct macb_config fu540_c000_config = {
- + .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_JUMBO |
- + MACB_CAPS_GEM_HAS_PTP,
- + .dma_burst_length = 16,
- + .clk_init = fu540_c000_clk_init,
- + .init = fu540_c000_init,
- + .jumbo_max_len = 10240,
- +};
- +
- static const struct macb_config at91sam9260_config = {
- .caps = MACB_CAPS_USRIO_HAS_CLKEN | MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII,
- .clk_init = macb_clk_init,
- @@ -4032,6 +4152,7 @@ static const struct of_device_id macb_dt_ids[] = {
- { .compatible = "cdns,emac", .data = &emac_config },
- { .compatible = "cdns,zynqmp-gem", .data = &zynqmp_config},
- { .compatible = "cdns,zynq-gem", .data = &zynq_config },
- + { .compatible = "sifive,fu540-macb", .data = &fu540_c000_config },
- { /* sentinel */ }
- };
- MODULE_DEVICE_TABLE(of, macb_dt_ids);
- @@ -4239,6 +4360,7 @@ static int macb_probe(struct platform_device *pdev)
-
- err_disable_clocks:
- clk_disable_unprepare(tx_clk);
- + clk_unregister(tx_clk);
- clk_disable_unprepare(hclk);
- clk_disable_unprepare(pclk);
- clk_disable_unprepare(rx_clk);
- @@ -4273,6 +4395,7 @@ static int macb_remove(struct platform_device *pdev)
- pm_runtime_dont_use_autosuspend(&pdev->dev);
- if (!pm_runtime_suspended(&pdev->dev)) {
- clk_disable_unprepare(bp->tx_clk);
- + clk_unregister(bp->tx_clk);
- clk_disable_unprepare(bp->hclk);
- clk_disable_unprepare(bp->pclk);
- clk_disable_unprepare(bp->rx_clk);
- --
- 2.22.0
|