Commit 102779c6 authored by David S. Miller's avatar David S. Miller

Merge branch 'macb-sama7g5'

Claudiu Beznea says:

====================
net: macb: add support for sama7g5

This series adds support for SAMA7G5 Ethernet interfaces: one 10/100Mbps
and one 1Gbps interfaces.

Along with it I also included a fix to disable clocks for SiFive FU540-C000
on failure path of fu540_c000_clk_init().

Thank you,
Claudiu Beznea

Changed in v3:
- use clk_bulk_disable_unprepare in patch 3/8
- corrected clang compilation warning in patch 3/8
- revert changes in macb_clk_init() in patch 3/8

Changes in v2:
- introduced patch "net: macb: add function to disable all macb clocks" and
  update patch "net: macb: unprepare clocks in case of failure" accordingly
- collected tags
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 102e2c07 700d566e
......@@ -16,6 +16,8 @@ Required properties:
Use "cdns,zynq-gem" Xilinx Zynq-7xxx SoC.
Use "cdns,zynqmp-gem" for Zynq Ultrascale+ MPSoC.
Use "sifive,fu540-c000-gem" for SiFive FU540-C000 SoC.
Use "microchip,sama7g5-emac" for Microchip SAMA7G5 ethernet interface.
Use "microchip,sama7g5-gem" for Microchip SAMA7G5 gigabit ethernet interface.
Or the generic form: "cdns,emac".
- reg: Address and length of the register set for the device
For "sifive,fu540-c000-gem", second range is required to specify the
......
......@@ -699,6 +699,7 @@
#define MACB_CAPS_GEM_HAS_PTP 0x00000040
#define MACB_CAPS_BD_RD_PREFETCH 0x00000080
#define MACB_CAPS_NEEDS_RSTONUBR 0x00000100
#define MACB_CAPS_CLK_HW_CHG 0x04000000
#define MACB_CAPS_MACB_IS_EMAC 0x08000000
#define MACB_CAPS_FIFO_MODE 0x10000000
#define MACB_CAPS_GIGABIT_MODE_AVAILABLE 0x20000000
......@@ -1147,6 +1148,14 @@ struct macb_pm_data {
u32 usrio;
};
struct macb_usrio_config {
u32 mii;
u32 rmii;
u32 rgmii;
u32 refclk;
u32 hdfctlen;
};
struct macb_config {
u32 caps;
unsigned int dma_burst_length;
......@@ -1155,6 +1164,7 @@ struct macb_config {
struct clk **rx_clk, struct clk **tsu_clk);
int (*init)(struct platform_device *pdev);
int jumbo_max_len;
const struct macb_usrio_config *usrio;
};
struct tsu_incr {
......@@ -1288,6 +1298,7 @@ struct macb {
u32 rx_intr_mask;
struct macb_pm_data pm_data;
const struct macb_usrio_config *usrio;
};
#ifdef CONFIG_MACB_USE_HWSTAMP
......
......@@ -460,15 +460,14 @@ static void macb_init_buffers(struct macb *bp)
/**
* macb_set_tx_clk() - Set a clock to a new frequency
* @clk: Pointer to the clock to change
* @bp: pointer to struct macb
* @speed: New frequency in Hz
* @dev: Pointer to the struct net_device
*/
static void macb_set_tx_clk(struct clk *clk, int speed, struct net_device *dev)
static void macb_set_tx_clk(struct macb *bp, int speed)
{
long ferr, rate, rate_rounded;
if (!clk)
if (!bp->tx_clk || !(bp->caps & MACB_CAPS_CLK_HW_CHG))
return;
switch (speed) {
......@@ -485,7 +484,7 @@ static void macb_set_tx_clk(struct clk *clk, int speed, struct net_device *dev)
return;
}
rate_rounded = clk_round_rate(clk, rate);
rate_rounded = clk_round_rate(bp->tx_clk, rate);
if (rate_rounded < 0)
return;
......@@ -495,11 +494,12 @@ static void macb_set_tx_clk(struct clk *clk, int speed, struct net_device *dev)
ferr = abs(rate_rounded - rate);
ferr = DIV_ROUND_UP(ferr, rate / 100000);
if (ferr > 5)
netdev_warn(dev, "unable to generate target frequency: %ld Hz\n",
netdev_warn(bp->dev,
"unable to generate target frequency: %ld Hz\n",
rate);
if (clk_set_rate(clk, rate_rounded))
netdev_err(dev, "adjusting tx_clk failed.\n");
if (clk_set_rate(bp->tx_clk, rate_rounded))
netdev_err(bp->dev, "adjusting tx_clk failed.\n");
}
static void macb_validate(struct phylink_config *config,
......@@ -751,7 +751,7 @@ static void macb_mac_link_up(struct phylink_config *config,
if (rx_pause)
ctrl |= MACB_BIT(PAE);
macb_set_tx_clk(bp->tx_clk, speed, ndev);
macb_set_tx_clk(bp, speed);
/* Initialize rings & buffers as clearing MACB_BIT(TE) in link down
* cleared the pipeline and control registers.
......@@ -3694,6 +3694,20 @@ static void macb_probe_queues(void __iomem *mem,
*num_queues = hweight32(*queue_mask);
}
static void macb_clks_disable(struct clk *pclk, struct clk *hclk, struct clk *tx_clk,
struct clk *rx_clk, struct clk *tsu_clk)
{
struct clk_bulk_data clks[] = {
{ .clk = tsu_clk, },
{ .clk = rx_clk, },
{ .clk = pclk, },
{ .clk = hclk, },
{ .clk = tx_clk },
};
clk_bulk_disable_unprepare(ARRAY_SIZE(clks), clks);
}
static int macb_clk_init(struct platform_device *pdev, struct clk **pclk,
struct clk **hclk, struct clk **tx_clk,
struct clk **rx_clk, struct clk **tsu_clk)
......@@ -3913,15 +3927,15 @@ static int macb_init(struct platform_device *pdev)
if (!(bp->caps & MACB_CAPS_USRIO_DISABLED)) {
val = 0;
if (phy_interface_mode_is_rgmii(bp->phy_interface))
val = GEM_BIT(RGMII);
val = bp->usrio->rgmii;
else if (bp->phy_interface == PHY_INTERFACE_MODE_RMII &&
(bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII))
val = MACB_BIT(RMII);
val = bp->usrio->rmii;
else if (!(bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII))
val = MACB_BIT(MII);
val = bp->usrio->mii;
if (bp->caps & MACB_CAPS_USRIO_HAS_CLKEN)
val |= MACB_BIT(CLKEN);
val |= bp->usrio->refclk;
macb_or_gem_writel(bp, USRIO, val);
}
......@@ -4406,8 +4420,10 @@ static int fu540_c000_clk_init(struct platform_device *pdev, struct clk **pclk,
return err;
mgmt = devm_kzalloc(&pdev->dev, sizeof(*mgmt), GFP_KERNEL);
if (!mgmt)
return -ENOMEM;
if (!mgmt) {
err = -ENOMEM;
goto err_disable_clks;
}
init.name = "sifive-gemgxl-mgmt";
init.ops = &fu540_c000_ops;
......@@ -4418,16 +4434,26 @@ static int fu540_c000_clk_init(struct platform_device *pdev, struct clk **pclk,
mgmt->hw.init = &init;
*tx_clk = devm_clk_register(&pdev->dev, &mgmt->hw);
if (IS_ERR(*tx_clk))
return PTR_ERR(*tx_clk);
if (IS_ERR(*tx_clk)) {
err = PTR_ERR(*tx_clk);
goto err_disable_clks;
}
err = clk_prepare_enable(*tx_clk);
if (err)
if (err) {
dev_err(&pdev->dev, "failed to enable tx_clk (%u)\n", err);
else
*tx_clk = NULL;
goto err_disable_clks;
} else {
dev_info(&pdev->dev, "Registered clk switch '%s'\n", init.name);
}
return 0;
err_disable_clks:
macb_clks_disable(*pclk, *hclk, *tx_clk, *rx_clk, *tsu_clk);
return err;
}
static int fu540_c000_init(struct platform_device *pdev)
......@@ -4439,6 +4465,21 @@ static int fu540_c000_init(struct platform_device *pdev)
return macb_init(pdev);
}
static const struct macb_usrio_config macb_default_usrio = {
.mii = MACB_BIT(MII),
.rmii = MACB_BIT(RMII),
.rgmii = GEM_BIT(RGMII),
.refclk = MACB_BIT(CLKEN),
};
static const struct macb_usrio_config sama7g5_usrio = {
.mii = 0,
.rmii = 1,
.rgmii = 2,
.refclk = BIT(2),
.hdfctlen = BIT(6),
};
static const struct macb_config fu540_c000_config = {
.caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_JUMBO |
MACB_CAPS_GEM_HAS_PTP,
......@@ -4446,12 +4487,14 @@ static const struct macb_config fu540_c000_config = {
.clk_init = fu540_c000_clk_init,
.init = fu540_c000_init,
.jumbo_max_len = 10240,
.usrio = &macb_default_usrio,
};
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,
.init = macb_init,
.usrio = &macb_default_usrio,
};
static const struct macb_config sama5d3macb_config = {
......@@ -4459,6 +4502,7 @@ static const struct macb_config sama5d3macb_config = {
| MACB_CAPS_USRIO_HAS_CLKEN | MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII,
.clk_init = macb_clk_init,
.init = macb_init,
.usrio = &macb_default_usrio,
};
static const struct macb_config pc302gem_config = {
......@@ -4466,6 +4510,7 @@ static const struct macb_config pc302gem_config = {
.dma_burst_length = 16,
.clk_init = macb_clk_init,
.init = macb_init,
.usrio = &macb_default_usrio,
};
static const struct macb_config sama5d2_config = {
......@@ -4473,6 +4518,7 @@ static const struct macb_config sama5d2_config = {
.dma_burst_length = 16,
.clk_init = macb_clk_init,
.init = macb_init,
.usrio = &macb_default_usrio,
};
static const struct macb_config sama5d3_config = {
......@@ -4482,6 +4528,7 @@ static const struct macb_config sama5d3_config = {
.clk_init = macb_clk_init,
.init = macb_init,
.jumbo_max_len = 10240,
.usrio = &macb_default_usrio,
};
static const struct macb_config sama5d4_config = {
......@@ -4489,18 +4536,21 @@ static const struct macb_config sama5d4_config = {
.dma_burst_length = 4,
.clk_init = macb_clk_init,
.init = macb_init,
.usrio = &macb_default_usrio,
};
static const struct macb_config emac_config = {
.caps = MACB_CAPS_NEEDS_RSTONUBR | MACB_CAPS_MACB_IS_EMAC,
.clk_init = at91ether_clk_init,
.init = at91ether_init,
.usrio = &macb_default_usrio,
};
static const struct macb_config np4_config = {
.caps = MACB_CAPS_USRIO_DISABLED,
.clk_init = macb_clk_init,
.init = macb_init,
.usrio = &macb_default_usrio,
};
static const struct macb_config zynqmp_config = {
......@@ -4511,6 +4561,7 @@ static const struct macb_config zynqmp_config = {
.clk_init = macb_clk_init,
.init = macb_init,
.jumbo_max_len = 10240,
.usrio = &macb_default_usrio,
};
static const struct macb_config zynq_config = {
......@@ -4519,6 +4570,23 @@ static const struct macb_config zynq_config = {
.dma_burst_length = 16,
.clk_init = macb_clk_init,
.init = macb_init,
.usrio = &macb_default_usrio,
};
static const struct macb_config sama7g5_gem_config = {
.caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_CLK_HW_CHG,
.dma_burst_length = 16,
.clk_init = macb_clk_init,
.init = macb_init,
.usrio = &sama7g5_usrio,
};
static const struct macb_config sama7g5_emac_config = {
.caps = MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII | MACB_CAPS_USRIO_HAS_CLKEN,
.dma_burst_length = 16,
.clk_init = macb_clk_init,
.init = macb_init,
.usrio = &sama7g5_usrio,
};
static const struct of_device_id macb_dt_ids[] = {
......@@ -4538,6 +4606,8 @@ static const struct of_device_id macb_dt_ids[] = {
{ .compatible = "cdns,zynqmp-gem", .data = &zynqmp_config},
{ .compatible = "cdns,zynq-gem", .data = &zynq_config },
{ .compatible = "sifive,fu540-c000-gem", .data = &fu540_c000_config },
{ .compatible = "microchip,sama7g5-gem", .data = &sama7g5_gem_config },
{ .compatible = "microchip,sama7g5-emac", .data = &sama7g5_emac_config },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, macb_dt_ids);
......@@ -4640,6 +4710,8 @@ static int macb_probe(struct platform_device *pdev)
bp->wol |= MACB_WOL_HAS_MAGIC_PACKET;
device_set_wakeup_capable(&pdev->dev, bp->wol & MACB_WOL_HAS_MAGIC_PACKET);
bp->usrio = macb_config->usrio;
spin_lock_init(&bp->lock);
/* setup capabilities */
......@@ -4735,11 +4807,7 @@ static int macb_probe(struct platform_device *pdev)
free_netdev(dev);
err_disable_clocks:
clk_disable_unprepare(tx_clk);
clk_disable_unprepare(hclk);
clk_disable_unprepare(pclk);
clk_disable_unprepare(rx_clk);
clk_disable_unprepare(tsu_clk);
macb_clks_disable(pclk, hclk, tx_clk, rx_clk, tsu_clk);
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
......@@ -4764,11 +4832,8 @@ static int macb_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev);
if (!pm_runtime_suspended(&pdev->dev)) {
clk_disable_unprepare(bp->tx_clk);
clk_disable_unprepare(bp->hclk);
clk_disable_unprepare(bp->pclk);
clk_disable_unprepare(bp->rx_clk);
clk_disable_unprepare(bp->tsu_clk);
macb_clks_disable(bp->pclk, bp->hclk, bp->tx_clk,
bp->rx_clk, bp->tsu_clk);
pm_runtime_set_suspended(&pdev->dev);
}
phylink_destroy(bp->phylink);
......@@ -4947,13 +5012,10 @@ static int __maybe_unused macb_runtime_suspend(struct device *dev)
struct net_device *netdev = dev_get_drvdata(dev);
struct macb *bp = netdev_priv(netdev);
if (!(device_may_wakeup(dev))) {
clk_disable_unprepare(bp->tx_clk);
clk_disable_unprepare(bp->hclk);
clk_disable_unprepare(bp->pclk);
clk_disable_unprepare(bp->rx_clk);
}
clk_disable_unprepare(bp->tsu_clk);
if (!(device_may_wakeup(dev)))
macb_clks_disable(bp->pclk, bp->hclk, bp->tx_clk, bp->rx_clk, bp->tsu_clk);
else
macb_clks_disable(NULL, NULL, NULL, NULL, bp->tsu_clk);
return 0;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment