Re: [PATCH v2 2/2] macb: Add support for SiFive FU540-C000

From: Andrew Lunn
Date: Mon Jun 17 2019 - 12:03:38 EST


On Mon, Jun 17, 2019 at 09:49:27AM +0530, Yash Shah wrote:
> 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@xxxxxxxxxx>
> ---
> drivers/net/ethernet/cadence/Kconfig | 6 ++
> drivers/net/ethernet/cadence/macb_main.c | 129 +++++++++++++++++++++++++++++++
> 2 files changed, 135 insertions(+)
>
> diff --git a/drivers/net/ethernet/cadence/Kconfig b/drivers/net/ethernet/cadence/Kconfig
> index b998401..d478fae 100644
> --- a/drivers/net/ethernet/cadence/Kconfig
> +++ b/drivers/net/ethernet/cadence/Kconfig
> @@ -48,4 +48,10 @@ config MACB_PCI
> To compile this driver as a module, choose M here: the module
> will be called macb_pci.
>
> +config MACB_SIFIVE_FU540
> + bool "Cadence MACB/GEM support for SiFive FU540 SoC"
> + depends on MACB && GPIO_SIFIVE
> + help
> + Enable the Cadence MACB/GEM support for SiFive FU540 SoC.
> +
> endif # NET_VENDOR_CADENCE
> diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
> index c049410..275b5e8 100644
> --- a/drivers/net/ethernet/cadence/macb_main.c
> +++ b/drivers/net/ethernet/cadence/macb_main.c
> @@ -10,6 +10,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>
> @@ -40,6 +41,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 */
>
> @@ -3903,6 +3913,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,
> @@ -3992,6 +4112,9 @@ static int at91ether_init(struct platform_device *pdev)
> { .compatible = "cdns,emac", .data = &emac_config },
> { .compatible = "cdns,zynqmp-gem", .data = &zynqmp_config},
> { .compatible = "cdns,zynq-gem", .data = &zynq_config },
> +#ifdef CONFIG_MACB_SIFIVE_FU540
> + { .compatible = "sifive,fu540-macb", .data = &fu540_c000_config },
> +#endif

This #ifdef should not be needed.

> { /* sentinel */ }
> };
> MODULE_DEVICE_TABLE(of, macb_dt_ids);
> @@ -4199,6 +4322,9 @@ static int macb_probe(struct platform_device *pdev)
>
> err_disable_clocks:
> clk_disable_unprepare(tx_clk);
> +#ifdef CONFIG_MACB_SIFIVE_FU540
> + clk_unregister(tx_clk);
> +#endif

So long as tx_clk is NULL, you can call clk_unregister(). So please
remove the #ifdef.


> clk_disable_unprepare(hclk);
> clk_disable_unprepare(pclk);
> clk_disable_unprepare(rx_clk);
> @@ -4233,6 +4359,9 @@ 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);
> +#ifdef CONFIG_MACB_SIFIVE_FU540
> + clk_unregister(bp->tx_clk);
> +#endif

Same here.

In general try to avoid #ifdef in C code.

Andrew