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: ...@@ -16,6 +16,8 @@ Required properties:
Use "cdns,zynq-gem" Xilinx Zynq-7xxx SoC. Use "cdns,zynq-gem" Xilinx Zynq-7xxx SoC.
Use "cdns,zynqmp-gem" for Zynq Ultrascale+ MPSoC. Use "cdns,zynqmp-gem" for Zynq Ultrascale+ MPSoC.
Use "sifive,fu540-c000-gem" for SiFive FU540-C000 SoC. 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". Or the generic form: "cdns,emac".
- reg: Address and length of the register set for the device - reg: Address and length of the register set for the device
For "sifive,fu540-c000-gem", second range is required to specify the For "sifive,fu540-c000-gem", second range is required to specify the
......
...@@ -699,6 +699,7 @@ ...@@ -699,6 +699,7 @@
#define MACB_CAPS_GEM_HAS_PTP 0x00000040 #define MACB_CAPS_GEM_HAS_PTP 0x00000040
#define MACB_CAPS_BD_RD_PREFETCH 0x00000080 #define MACB_CAPS_BD_RD_PREFETCH 0x00000080
#define MACB_CAPS_NEEDS_RSTONUBR 0x00000100 #define MACB_CAPS_NEEDS_RSTONUBR 0x00000100
#define MACB_CAPS_CLK_HW_CHG 0x04000000
#define MACB_CAPS_MACB_IS_EMAC 0x08000000 #define MACB_CAPS_MACB_IS_EMAC 0x08000000
#define MACB_CAPS_FIFO_MODE 0x10000000 #define MACB_CAPS_FIFO_MODE 0x10000000
#define MACB_CAPS_GIGABIT_MODE_AVAILABLE 0x20000000 #define MACB_CAPS_GIGABIT_MODE_AVAILABLE 0x20000000
...@@ -1147,6 +1148,14 @@ struct macb_pm_data { ...@@ -1147,6 +1148,14 @@ struct macb_pm_data {
u32 usrio; u32 usrio;
}; };
struct macb_usrio_config {
u32 mii;
u32 rmii;
u32 rgmii;
u32 refclk;
u32 hdfctlen;
};
struct macb_config { struct macb_config {
u32 caps; u32 caps;
unsigned int dma_burst_length; unsigned int dma_burst_length;
...@@ -1155,6 +1164,7 @@ struct macb_config { ...@@ -1155,6 +1164,7 @@ struct macb_config {
struct clk **rx_clk, struct clk **tsu_clk); struct clk **rx_clk, struct clk **tsu_clk);
int (*init)(struct platform_device *pdev); int (*init)(struct platform_device *pdev);
int jumbo_max_len; int jumbo_max_len;
const struct macb_usrio_config *usrio;
}; };
struct tsu_incr { struct tsu_incr {
...@@ -1288,6 +1298,7 @@ struct macb { ...@@ -1288,6 +1298,7 @@ struct macb {
u32 rx_intr_mask; u32 rx_intr_mask;
struct macb_pm_data pm_data; struct macb_pm_data pm_data;
const struct macb_usrio_config *usrio;
}; };
#ifdef CONFIG_MACB_USE_HWSTAMP #ifdef CONFIG_MACB_USE_HWSTAMP
......
...@@ -460,15 +460,14 @@ static void macb_init_buffers(struct macb *bp) ...@@ -460,15 +460,14 @@ static void macb_init_buffers(struct macb *bp)
/** /**
* macb_set_tx_clk() - Set a clock to a new frequency * 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 * @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; long ferr, rate, rate_rounded;
if (!clk) if (!bp->tx_clk || !(bp->caps & MACB_CAPS_CLK_HW_CHG))
return; return;
switch (speed) { switch (speed) {
...@@ -485,7 +484,7 @@ static void macb_set_tx_clk(struct clk *clk, int speed, struct net_device *dev) ...@@ -485,7 +484,7 @@ static void macb_set_tx_clk(struct clk *clk, int speed, struct net_device *dev)
return; return;
} }
rate_rounded = clk_round_rate(clk, rate); rate_rounded = clk_round_rate(bp->tx_clk, rate);
if (rate_rounded < 0) if (rate_rounded < 0)
return; return;
...@@ -495,11 +494,12 @@ static void macb_set_tx_clk(struct clk *clk, int speed, struct net_device *dev) ...@@ -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 = abs(rate_rounded - rate);
ferr = DIV_ROUND_UP(ferr, rate / 100000); ferr = DIV_ROUND_UP(ferr, rate / 100000);
if (ferr > 5) 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); rate);
if (clk_set_rate(clk, rate_rounded)) if (clk_set_rate(bp->tx_clk, rate_rounded))
netdev_err(dev, "adjusting tx_clk failed.\n"); netdev_err(bp->dev, "adjusting tx_clk failed.\n");
} }
static void macb_validate(struct phylink_config *config, static void macb_validate(struct phylink_config *config,
...@@ -751,7 +751,7 @@ static void macb_mac_link_up(struct phylink_config *config, ...@@ -751,7 +751,7 @@ static void macb_mac_link_up(struct phylink_config *config,
if (rx_pause) if (rx_pause)
ctrl |= MACB_BIT(PAE); 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 /* Initialize rings & buffers as clearing MACB_BIT(TE) in link down
* cleared the pipeline and control registers. * cleared the pipeline and control registers.
...@@ -3694,6 +3694,20 @@ static void macb_probe_queues(void __iomem *mem, ...@@ -3694,6 +3694,20 @@ static void macb_probe_queues(void __iomem *mem,
*num_queues = hweight32(*queue_mask); *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, static int macb_clk_init(struct platform_device *pdev, struct clk **pclk,
struct clk **hclk, struct clk **tx_clk, struct clk **hclk, struct clk **tx_clk,
struct clk **rx_clk, struct clk **tsu_clk) struct clk **rx_clk, struct clk **tsu_clk)
...@@ -3913,15 +3927,15 @@ static int macb_init(struct platform_device *pdev) ...@@ -3913,15 +3927,15 @@ static int macb_init(struct platform_device *pdev)
if (!(bp->caps & MACB_CAPS_USRIO_DISABLED)) { if (!(bp->caps & MACB_CAPS_USRIO_DISABLED)) {
val = 0; val = 0;
if (phy_interface_mode_is_rgmii(bp->phy_interface)) 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 && else if (bp->phy_interface == PHY_INTERFACE_MODE_RMII &&
(bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII)) (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)) 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) if (bp->caps & MACB_CAPS_USRIO_HAS_CLKEN)
val |= MACB_BIT(CLKEN); val |= bp->usrio->refclk;
macb_or_gem_writel(bp, USRIO, val); macb_or_gem_writel(bp, USRIO, val);
} }
...@@ -4406,8 +4420,10 @@ static int fu540_c000_clk_init(struct platform_device *pdev, struct clk **pclk, ...@@ -4406,8 +4420,10 @@ static int fu540_c000_clk_init(struct platform_device *pdev, struct clk **pclk,
return err; return err;
mgmt = devm_kzalloc(&pdev->dev, sizeof(*mgmt), GFP_KERNEL); mgmt = devm_kzalloc(&pdev->dev, sizeof(*mgmt), GFP_KERNEL);
if (!mgmt) if (!mgmt) {
return -ENOMEM; err = -ENOMEM;
goto err_disable_clks;
}
init.name = "sifive-gemgxl-mgmt"; init.name = "sifive-gemgxl-mgmt";
init.ops = &fu540_c000_ops; init.ops = &fu540_c000_ops;
...@@ -4418,16 +4434,26 @@ static int fu540_c000_clk_init(struct platform_device *pdev, struct clk **pclk, ...@@ -4418,16 +4434,26 @@ static int fu540_c000_clk_init(struct platform_device *pdev, struct clk **pclk,
mgmt->hw.init = &init; mgmt->hw.init = &init;
*tx_clk = devm_clk_register(&pdev->dev, &mgmt->hw); *tx_clk = devm_clk_register(&pdev->dev, &mgmt->hw);
if (IS_ERR(*tx_clk)) if (IS_ERR(*tx_clk)) {
return PTR_ERR(*tx_clk); err = PTR_ERR(*tx_clk);
goto err_disable_clks;
}
err = clk_prepare_enable(*tx_clk); err = clk_prepare_enable(*tx_clk);
if (err) if (err) {
dev_err(&pdev->dev, "failed to enable tx_clk (%u)\n", 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); dev_info(&pdev->dev, "Registered clk switch '%s'\n", init.name);
}
return 0; 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) static int fu540_c000_init(struct platform_device *pdev)
...@@ -4439,6 +4465,21 @@ 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); 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 = { static const struct macb_config fu540_c000_config = {
.caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_JUMBO | .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_JUMBO |
MACB_CAPS_GEM_HAS_PTP, MACB_CAPS_GEM_HAS_PTP,
...@@ -4446,12 +4487,14 @@ static const struct macb_config fu540_c000_config = { ...@@ -4446,12 +4487,14 @@ static const struct macb_config fu540_c000_config = {
.clk_init = fu540_c000_clk_init, .clk_init = fu540_c000_clk_init,
.init = fu540_c000_init, .init = fu540_c000_init,
.jumbo_max_len = 10240, .jumbo_max_len = 10240,
.usrio = &macb_default_usrio,
}; };
static const struct macb_config at91sam9260_config = { static const struct macb_config at91sam9260_config = {
.caps = MACB_CAPS_USRIO_HAS_CLKEN | MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII, .caps = MACB_CAPS_USRIO_HAS_CLKEN | MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII,
.clk_init = macb_clk_init, .clk_init = macb_clk_init,
.init = macb_init, .init = macb_init,
.usrio = &macb_default_usrio,
}; };
static const struct macb_config sama5d3macb_config = { static const struct macb_config sama5d3macb_config = {
...@@ -4459,6 +4502,7 @@ 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, | MACB_CAPS_USRIO_HAS_CLKEN | MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII,
.clk_init = macb_clk_init, .clk_init = macb_clk_init,
.init = macb_init, .init = macb_init,
.usrio = &macb_default_usrio,
}; };
static const struct macb_config pc302gem_config = { static const struct macb_config pc302gem_config = {
...@@ -4466,6 +4510,7 @@ static const struct macb_config pc302gem_config = { ...@@ -4466,6 +4510,7 @@ static const struct macb_config pc302gem_config = {
.dma_burst_length = 16, .dma_burst_length = 16,
.clk_init = macb_clk_init, .clk_init = macb_clk_init,
.init = macb_init, .init = macb_init,
.usrio = &macb_default_usrio,
}; };
static const struct macb_config sama5d2_config = { static const struct macb_config sama5d2_config = {
...@@ -4473,6 +4518,7 @@ static const struct macb_config sama5d2_config = { ...@@ -4473,6 +4518,7 @@ static const struct macb_config sama5d2_config = {
.dma_burst_length = 16, .dma_burst_length = 16,
.clk_init = macb_clk_init, .clk_init = macb_clk_init,
.init = macb_init, .init = macb_init,
.usrio = &macb_default_usrio,
}; };
static const struct macb_config sama5d3_config = { static const struct macb_config sama5d3_config = {
...@@ -4482,6 +4528,7 @@ static const struct macb_config sama5d3_config = { ...@@ -4482,6 +4528,7 @@ static const struct macb_config sama5d3_config = {
.clk_init = macb_clk_init, .clk_init = macb_clk_init,
.init = macb_init, .init = macb_init,
.jumbo_max_len = 10240, .jumbo_max_len = 10240,
.usrio = &macb_default_usrio,
}; };
static const struct macb_config sama5d4_config = { static const struct macb_config sama5d4_config = {
...@@ -4489,18 +4536,21 @@ static const struct macb_config sama5d4_config = { ...@@ -4489,18 +4536,21 @@ static const struct macb_config sama5d4_config = {
.dma_burst_length = 4, .dma_burst_length = 4,
.clk_init = macb_clk_init, .clk_init = macb_clk_init,
.init = macb_init, .init = macb_init,
.usrio = &macb_default_usrio,
}; };
static const struct macb_config emac_config = { static const struct macb_config emac_config = {
.caps = MACB_CAPS_NEEDS_RSTONUBR | MACB_CAPS_MACB_IS_EMAC, .caps = MACB_CAPS_NEEDS_RSTONUBR | MACB_CAPS_MACB_IS_EMAC,
.clk_init = at91ether_clk_init, .clk_init = at91ether_clk_init,
.init = at91ether_init, .init = at91ether_init,
.usrio = &macb_default_usrio,
}; };
static const struct macb_config np4_config = { static const struct macb_config np4_config = {
.caps = MACB_CAPS_USRIO_DISABLED, .caps = MACB_CAPS_USRIO_DISABLED,
.clk_init = macb_clk_init, .clk_init = macb_clk_init,
.init = macb_init, .init = macb_init,
.usrio = &macb_default_usrio,
}; };
static const struct macb_config zynqmp_config = { static const struct macb_config zynqmp_config = {
...@@ -4511,6 +4561,7 @@ static const struct macb_config zynqmp_config = { ...@@ -4511,6 +4561,7 @@ static const struct macb_config zynqmp_config = {
.clk_init = macb_clk_init, .clk_init = macb_clk_init,
.init = macb_init, .init = macb_init,
.jumbo_max_len = 10240, .jumbo_max_len = 10240,
.usrio = &macb_default_usrio,
}; };
static const struct macb_config zynq_config = { static const struct macb_config zynq_config = {
...@@ -4519,6 +4570,23 @@ static const struct macb_config zynq_config = { ...@@ -4519,6 +4570,23 @@ static const struct macb_config zynq_config = {
.dma_burst_length = 16, .dma_burst_length = 16,
.clk_init = macb_clk_init, .clk_init = macb_clk_init,
.init = macb_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[] = { static const struct of_device_id macb_dt_ids[] = {
...@@ -4538,6 +4606,8 @@ 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,zynqmp-gem", .data = &zynqmp_config},
{ .compatible = "cdns,zynq-gem", .data = &zynq_config }, { .compatible = "cdns,zynq-gem", .data = &zynq_config },
{ .compatible = "sifive,fu540-c000-gem", .data = &fu540_c000_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 */ } { /* sentinel */ }
}; };
MODULE_DEVICE_TABLE(of, macb_dt_ids); MODULE_DEVICE_TABLE(of, macb_dt_ids);
...@@ -4640,6 +4710,8 @@ static int macb_probe(struct platform_device *pdev) ...@@ -4640,6 +4710,8 @@ static int macb_probe(struct platform_device *pdev)
bp->wol |= MACB_WOL_HAS_MAGIC_PACKET; bp->wol |= MACB_WOL_HAS_MAGIC_PACKET;
device_set_wakeup_capable(&pdev->dev, 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); spin_lock_init(&bp->lock);
/* setup capabilities */ /* setup capabilities */
...@@ -4735,11 +4807,7 @@ static int macb_probe(struct platform_device *pdev) ...@@ -4735,11 +4807,7 @@ static int macb_probe(struct platform_device *pdev)
free_netdev(dev); free_netdev(dev);
err_disable_clocks: err_disable_clocks:
clk_disable_unprepare(tx_clk); macb_clks_disable(pclk, hclk, tx_clk, rx_clk, tsu_clk);
clk_disable_unprepare(hclk);
clk_disable_unprepare(pclk);
clk_disable_unprepare(rx_clk);
clk_disable_unprepare(tsu_clk);
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev); pm_runtime_set_suspended(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev);
...@@ -4764,11 +4832,8 @@ static int macb_remove(struct platform_device *pdev) ...@@ -4764,11 +4832,8 @@ static int macb_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev); pm_runtime_disable(&pdev->dev);
pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev);
if (!pm_runtime_suspended(&pdev->dev)) { if (!pm_runtime_suspended(&pdev->dev)) {
clk_disable_unprepare(bp->tx_clk); macb_clks_disable(bp->pclk, bp->hclk, bp->tx_clk,
clk_disable_unprepare(bp->hclk); bp->rx_clk, bp->tsu_clk);
clk_disable_unprepare(bp->pclk);
clk_disable_unprepare(bp->rx_clk);
clk_disable_unprepare(bp->tsu_clk);
pm_runtime_set_suspended(&pdev->dev); pm_runtime_set_suspended(&pdev->dev);
} }
phylink_destroy(bp->phylink); phylink_destroy(bp->phylink);
...@@ -4947,13 +5012,10 @@ static int __maybe_unused macb_runtime_suspend(struct device *dev) ...@@ -4947,13 +5012,10 @@ static int __maybe_unused macb_runtime_suspend(struct device *dev)
struct net_device *netdev = dev_get_drvdata(dev); struct net_device *netdev = dev_get_drvdata(dev);
struct macb *bp = netdev_priv(netdev); struct macb *bp = netdev_priv(netdev);
if (!(device_may_wakeup(dev))) { if (!(device_may_wakeup(dev)))
clk_disable_unprepare(bp->tx_clk); macb_clks_disable(bp->pclk, bp->hclk, bp->tx_clk, bp->rx_clk, bp->tsu_clk);
clk_disable_unprepare(bp->hclk); else
clk_disable_unprepare(bp->pclk); macb_clks_disable(NULL, NULL, NULL, NULL, bp->tsu_clk);
clk_disable_unprepare(bp->rx_clk);
}
clk_disable_unprepare(bp->tsu_clk);
return 0; 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