Commit 5cf15ce3 authored by David S. Miller's avatar David S. Miller

Merge branch 'Renesas-RSZ-V2M-support'

Phil Edworthy says:

====================
Add Renesas RZ/V2M Ethernet support

The RZ/V2M Ethernet is very similar to R-Car Gen3 Ethernet-AVB, though
some small parts are the same as R-Car Gen2.
Other differences are:
* It has separate data (DI), error (Line 1) and management (Line 2) irqs
  rather than one irq for all three.
* Instead of using the High-speed peripheral bus clock for gPTP, it has
  a separate gPTP reference clock.

v4:
 * Add clk_disable_unprepare() for gptp ref clk

v3:
 * Really renamed irq_en_dis_regs to irq_en_dis this time
 * Modified ravb_ptp_extts() to use irq_en_dis
 * Added Reviewed-by tags

v2:
 * Just net patches in this series
 * Instead of reusing ch22 and ch24 interrupt names, use the proper names
 * Renamed irq_en_dis_regs to irq_en_dis
 * Squashed use of GIC reg versus GIE/GID and got rid of separate gptp_ptm_gic feature.
 * Move err_mgmt_irqs code under multi_irqs
 * Minor editing of the commit msgs
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 1a01a075 e1154be7
...@@ -43,6 +43,11 @@ properties: ...@@ -43,6 +43,11 @@ properties:
- renesas,etheravb-r8a779a0 # R-Car V3U - renesas,etheravb-r8a779a0 # R-Car V3U
- const: renesas,etheravb-rcar-gen3 # R-Car Gen3 and RZ/G2 - const: renesas,etheravb-rcar-gen3 # R-Car Gen3 and RZ/G2
- items:
- enum:
- renesas,etheravb-r9a09g011 # RZ/V2M
- const: renesas,etheravb-rzv2m # RZ/V2M compatible
- items: - items:
- enum: - enum:
- renesas,r9a07g043-gbeth # RZ/G2UL - renesas,r9a07g043-gbeth # RZ/G2UL
...@@ -160,16 +165,33 @@ allOf: ...@@ -160,16 +165,33 @@ allOf:
- const: arp_ns - const: arp_ns
rx-internal-delay-ps: false rx-internal-delay-ps: false
else: else:
properties: if:
interrupts: properties:
minItems: 25 compatible:
maxItems: 25 contains:
interrupt-names: const: renesas,etheravb-rzv2m
items: then:
pattern: '^ch[0-9]+$' properties:
required: interrupts:
- interrupt-names minItems: 29
- rx-internal-delay-ps maxItems: 29
interrupt-names:
items:
pattern: '^(ch(1?)[0-9])|ch20|ch21|dia|dib|err_a|err_b|mgmt_a|mgmt_b|line3$'
rx-internal-delay-ps: false
required:
- interrupt-names
else:
properties:
interrupts:
minItems: 25
maxItems: 25
interrupt-names:
items:
pattern: '^ch[0-9]+$'
required:
- interrupt-names
- rx-internal-delay-ps
- if: - if:
properties: properties:
...@@ -231,17 +253,35 @@ allOf: ...@@ -231,17 +253,35 @@ allOf:
- const: chi - const: chi
- const: refclk - const: refclk
else: else:
properties: if:
clocks: properties:
minItems: 1 compatible:
items: contains:
- description: AVB functional clock const: renesas,etheravb-rzv2m
- description: Optional TXC reference clock then:
clock-names: properties:
minItems: 1 clocks:
items: items:
- const: fck - description: Main clock
- const: refclk - description: Coherent Hub Interface clock
- description: gPTP reference clock
clock-names:
items:
- const: axi
- const: chi
- const: gptp
else:
properties:
clocks:
minItems: 1
items:
- description: AVB functional clock
- description: Optional TXC reference clock
clock-names:
minItems: 1
items:
- const: fck
- const: refclk
additionalProperties: false additionalProperties: false
......
...@@ -1027,8 +1027,11 @@ struct ravb_hw_info { ...@@ -1027,8 +1027,11 @@ struct ravb_hw_info {
unsigned tx_counters:1; /* E-MAC has TX counters */ unsigned tx_counters:1; /* E-MAC has TX counters */
unsigned carrier_counters:1; /* E-MAC has carrier counters */ unsigned carrier_counters:1; /* E-MAC has carrier counters */
unsigned multi_irqs:1; /* AVB-DMAC and E-MAC has multiple irqs */ unsigned multi_irqs:1; /* AVB-DMAC and E-MAC has multiple irqs */
unsigned irq_en_dis:1; /* Has separate irq enable and disable regs */
unsigned err_mgmt_irqs:1; /* Line1 (Err) and Line2 (Mgmt) irqs are separate */
unsigned gptp:1; /* AVB-DMAC has gPTP support */ unsigned gptp:1; /* AVB-DMAC has gPTP support */
unsigned ccc_gac:1; /* AVB-DMAC has gPTP support active in config mode */ unsigned ccc_gac:1; /* AVB-DMAC has gPTP support active in config mode */
unsigned gptp_ref_clk:1; /* gPTP has separate reference clock */
unsigned nc_queues:1; /* AVB-DMAC has RX and TX NC queues */ unsigned nc_queues:1; /* AVB-DMAC has RX and TX NC queues */
unsigned magic_pkt:1; /* E-MAC supports magic packet detection */ unsigned magic_pkt:1; /* E-MAC supports magic packet detection */
unsigned half_duplex:1; /* E-MAC supports half duplex mode */ unsigned half_duplex:1; /* E-MAC supports half duplex mode */
...@@ -1040,6 +1043,7 @@ struct ravb_private { ...@@ -1040,6 +1043,7 @@ struct ravb_private {
void __iomem *addr; void __iomem *addr;
struct clk *clk; struct clk *clk;
struct clk *refclk; struct clk *refclk;
struct clk *gptp_clk;
struct mdiobb_ctrl mdiobb; struct mdiobb_ctrl mdiobb;
u32 num_rx_ring[NUM_RX_QUEUE]; u32 num_rx_ring[NUM_RX_QUEUE];
u32 num_tx_ring[NUM_TX_QUEUE]; u32 num_tx_ring[NUM_TX_QUEUE];
...@@ -1077,6 +1081,8 @@ struct ravb_private { ...@@ -1077,6 +1081,8 @@ struct ravb_private {
int msg_enable; int msg_enable;
int speed; int speed;
int emac_irq; int emac_irq;
int erra_irq;
int mgmta_irq;
int rx_irqs[NUM_RX_QUEUE]; int rx_irqs[NUM_RX_QUEUE];
int tx_irqs[NUM_TX_QUEUE]; int tx_irqs[NUM_TX_QUEUE];
......
...@@ -1124,7 +1124,7 @@ static bool ravb_queue_interrupt(struct net_device *ndev, int q) ...@@ -1124,7 +1124,7 @@ static bool ravb_queue_interrupt(struct net_device *ndev, int q)
if (((ris0 & ric0) & BIT(q)) || ((tis & tic) & BIT(q))) { if (((ris0 & ric0) & BIT(q)) || ((tis & tic) & BIT(q))) {
if (napi_schedule_prep(&priv->napi[q])) { if (napi_schedule_prep(&priv->napi[q])) {
/* Mask RX and TX interrupts */ /* Mask RX and TX interrupts */
if (!info->multi_irqs) { if (!info->irq_en_dis) {
ravb_write(ndev, ric0 & ~BIT(q), RIC0); ravb_write(ndev, ric0 & ~BIT(q), RIC0);
ravb_write(ndev, tic & ~BIT(q), TIC); ravb_write(ndev, tic & ~BIT(q), TIC);
} else { } else {
...@@ -1306,7 +1306,7 @@ static int ravb_poll(struct napi_struct *napi, int budget) ...@@ -1306,7 +1306,7 @@ static int ravb_poll(struct napi_struct *napi, int budget)
/* Re-enable RX/TX interrupts */ /* Re-enable RX/TX interrupts */
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
if (!info->multi_irqs) { if (!info->irq_en_dis) {
ravb_modify(ndev, RIC0, mask, mask); ravb_modify(ndev, RIC0, mask, mask);
ravb_modify(ndev, TIC, mask, mask); ravb_modify(ndev, TIC, mask, mask);
} else { } else {
...@@ -1798,12 +1798,23 @@ static int ravb_open(struct net_device *ndev) ...@@ -1798,12 +1798,23 @@ static int ravb_open(struct net_device *ndev)
ndev, dev, "ch19:tx_nc"); ndev, dev, "ch19:tx_nc");
if (error) if (error)
goto out_free_irq_nc_rx; goto out_free_irq_nc_rx;
if (info->err_mgmt_irqs) {
error = ravb_hook_irq(priv->erra_irq, ravb_multi_interrupt,
ndev, dev, "err_a");
if (error)
goto out_free_irq_nc_tx;
error = ravb_hook_irq(priv->mgmta_irq, ravb_multi_interrupt,
ndev, dev, "mgmt_a");
if (error)
goto out_free_irq_erra;
}
} }
/* Device init */ /* Device init */
error = ravb_dmac_init(ndev); error = ravb_dmac_init(ndev);
if (error) if (error)
goto out_free_irq_nc_tx; goto out_free_irq_mgmta;
ravb_emac_init(ndev); ravb_emac_init(ndev);
/* Initialise PTP Clock driver */ /* Initialise PTP Clock driver */
...@@ -1823,9 +1834,15 @@ static int ravb_open(struct net_device *ndev) ...@@ -1823,9 +1834,15 @@ static int ravb_open(struct net_device *ndev)
/* Stop PTP Clock driver */ /* Stop PTP Clock driver */
if (info->gptp) if (info->gptp)
ravb_ptp_stop(ndev); ravb_ptp_stop(ndev);
out_free_irq_nc_tx: out_free_irq_mgmta:
if (!info->multi_irqs) if (!info->multi_irqs)
goto out_free_irq; goto out_free_irq;
if (info->err_mgmt_irqs)
free_irq(priv->mgmta_irq, ndev);
out_free_irq_erra:
if (info->err_mgmt_irqs)
free_irq(priv->erra_irq, ndev);
out_free_irq_nc_tx:
free_irq(priv->tx_irqs[RAVB_NC], ndev); free_irq(priv->tx_irqs[RAVB_NC], ndev);
out_free_irq_nc_rx: out_free_irq_nc_rx:
free_irq(priv->rx_irqs[RAVB_NC], ndev); free_irq(priv->rx_irqs[RAVB_NC], ndev);
...@@ -2166,6 +2183,10 @@ static int ravb_close(struct net_device *ndev) ...@@ -2166,6 +2183,10 @@ static int ravb_close(struct net_device *ndev)
free_irq(priv->tx_irqs[RAVB_BE], ndev); free_irq(priv->tx_irqs[RAVB_BE], ndev);
free_irq(priv->rx_irqs[RAVB_BE], ndev); free_irq(priv->rx_irqs[RAVB_BE], ndev);
free_irq(priv->emac_irq, ndev); free_irq(priv->emac_irq, ndev);
if (info->err_mgmt_irqs) {
free_irq(priv->erra_irq, ndev);
free_irq(priv->mgmta_irq, ndev);
}
} }
free_irq(ndev->irq, ndev); free_irq(ndev->irq, ndev);
...@@ -2410,6 +2431,7 @@ static const struct ravb_hw_info ravb_gen3_hw_info = { ...@@ -2410,6 +2431,7 @@ static const struct ravb_hw_info ravb_gen3_hw_info = {
.internal_delay = 1, .internal_delay = 1,
.tx_counters = 1, .tx_counters = 1,
.multi_irqs = 1, .multi_irqs = 1,
.irq_en_dis = 1,
.ccc_gac = 1, .ccc_gac = 1,
.nc_queues = 1, .nc_queues = 1,
.magic_pkt = 1, .magic_pkt = 1,
...@@ -2438,6 +2460,31 @@ static const struct ravb_hw_info ravb_gen2_hw_info = { ...@@ -2438,6 +2460,31 @@ static const struct ravb_hw_info ravb_gen2_hw_info = {
.magic_pkt = 1, .magic_pkt = 1,
}; };
static const struct ravb_hw_info ravb_rzv2m_hw_info = {
.rx_ring_free = ravb_rx_ring_free_rcar,
.rx_ring_format = ravb_rx_ring_format_rcar,
.alloc_rx_desc = ravb_alloc_rx_desc_rcar,
.receive = ravb_rx_rcar,
.set_rate = ravb_set_rate_rcar,
.set_feature = ravb_set_features_rcar,
.dmac_init = ravb_dmac_init_rcar,
.emac_init = ravb_emac_init_rcar,
.gstrings_stats = ravb_gstrings_stats,
.gstrings_size = sizeof(ravb_gstrings_stats),
.net_hw_features = NETIF_F_RXCSUM,
.net_features = NETIF_F_RXCSUM,
.stats_len = ARRAY_SIZE(ravb_gstrings_stats),
.max_rx_len = RX_BUF_SZ + RAVB_ALIGN - 1,
.tccr_mask = TCCR_TSRQ0 | TCCR_TSRQ1 | TCCR_TSRQ2 | TCCR_TSRQ3,
.rx_max_buf_size = SZ_2K,
.multi_irqs = 1,
.err_mgmt_irqs = 1,
.gptp = 1,
.gptp_ref_clk = 1,
.nc_queues = 1,
.magic_pkt = 1,
};
static const struct ravb_hw_info gbeth_hw_info = { static const struct ravb_hw_info gbeth_hw_info = {
.rx_ring_free = ravb_rx_ring_free_gbeth, .rx_ring_free = ravb_rx_ring_free_gbeth,
.rx_ring_format = ravb_rx_ring_format_gbeth, .rx_ring_format = ravb_rx_ring_format_gbeth,
...@@ -2465,6 +2512,7 @@ static const struct of_device_id ravb_match_table[] = { ...@@ -2465,6 +2512,7 @@ static const struct of_device_id ravb_match_table[] = {
{ .compatible = "renesas,etheravb-rcar-gen2", .data = &ravb_gen2_hw_info }, { .compatible = "renesas,etheravb-rcar-gen2", .data = &ravb_gen2_hw_info },
{ .compatible = "renesas,etheravb-r8a7795", .data = &ravb_gen3_hw_info }, { .compatible = "renesas,etheravb-r8a7795", .data = &ravb_gen3_hw_info },
{ .compatible = "renesas,etheravb-rcar-gen3", .data = &ravb_gen3_hw_info }, { .compatible = "renesas,etheravb-rcar-gen3", .data = &ravb_gen3_hw_info },
{ .compatible = "renesas,etheravb-rzv2m", .data = &ravb_rzv2m_hw_info },
{ .compatible = "renesas,rzg2l-gbeth", .data = &gbeth_hw_info }, { .compatible = "renesas,rzg2l-gbeth", .data = &gbeth_hw_info },
{ } { }
}; };
...@@ -2473,11 +2521,15 @@ MODULE_DEVICE_TABLE(of, ravb_match_table); ...@@ -2473,11 +2521,15 @@ MODULE_DEVICE_TABLE(of, ravb_match_table);
static int ravb_set_gti(struct net_device *ndev) static int ravb_set_gti(struct net_device *ndev)
{ {
struct ravb_private *priv = netdev_priv(ndev); struct ravb_private *priv = netdev_priv(ndev);
const struct ravb_hw_info *info = priv->info;
struct device *dev = ndev->dev.parent; struct device *dev = ndev->dev.parent;
unsigned long rate; unsigned long rate;
uint64_t inc; uint64_t inc;
rate = clk_get_rate(priv->clk); if (info->gptp_ref_clk)
rate = clk_get_rate(priv->gptp_clk);
else
rate = clk_get_rate(priv->clk);
if (!rate) if (!rate)
return -EINVAL; return -EINVAL;
...@@ -2594,10 +2646,14 @@ static int ravb_probe(struct platform_device *pdev) ...@@ -2594,10 +2646,14 @@ static int ravb_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
pm_runtime_get_sync(&pdev->dev); pm_runtime_get_sync(&pdev->dev);
if (info->multi_irqs) if (info->multi_irqs) {
irq = platform_get_irq_byname(pdev, "ch22"); if (info->err_mgmt_irqs)
else irq = platform_get_irq_byname(pdev, "dia");
else
irq = platform_get_irq_byname(pdev, "ch22");
} else {
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
}
if (irq < 0) { if (irq < 0) {
error = irq; error = irq;
goto out_release; goto out_release;
...@@ -2639,7 +2695,10 @@ static int ravb_probe(struct platform_device *pdev) ...@@ -2639,7 +2695,10 @@ static int ravb_probe(struct platform_device *pdev)
of_property_read_bool(np, "renesas,ether-link-active-low"); of_property_read_bool(np, "renesas,ether-link-active-low");
if (info->multi_irqs) { if (info->multi_irqs) {
irq = platform_get_irq_byname(pdev, "ch24"); if (info->err_mgmt_irqs)
irq = platform_get_irq_byname(pdev, "line3");
else
irq = platform_get_irq_byname(pdev, "ch24");
if (irq < 0) { if (irq < 0) {
error = irq; error = irq;
goto out_release; goto out_release;
...@@ -2661,6 +2720,22 @@ static int ravb_probe(struct platform_device *pdev) ...@@ -2661,6 +2720,22 @@ static int ravb_probe(struct platform_device *pdev)
} }
priv->tx_irqs[i] = irq; priv->tx_irqs[i] = irq;
} }
if (info->err_mgmt_irqs) {
irq = platform_get_irq_byname(pdev, "err_a");
if (irq < 0) {
error = irq;
goto out_release;
}
priv->erra_irq = irq;
irq = platform_get_irq_byname(pdev, "mgmt_a");
if (irq < 0) {
error = irq;
goto out_release;
}
priv->mgmta_irq = irq;
}
} }
priv->clk = devm_clk_get(&pdev->dev, NULL); priv->clk = devm_clk_get(&pdev->dev, NULL);
...@@ -2676,6 +2751,15 @@ static int ravb_probe(struct platform_device *pdev) ...@@ -2676,6 +2751,15 @@ static int ravb_probe(struct platform_device *pdev)
} }
clk_prepare_enable(priv->refclk); clk_prepare_enable(priv->refclk);
if (info->gptp_ref_clk) {
priv->gptp_clk = devm_clk_get(&pdev->dev, "gptp");
if (IS_ERR(priv->gptp_clk)) {
error = PTR_ERR(priv->gptp_clk);
goto out_disable_refclk;
}
clk_prepare_enable(priv->gptp_clk);
}
ndev->max_mtu = info->rx_max_buf_size - (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN); ndev->max_mtu = info->rx_max_buf_size - (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN);
ndev->min_mtu = ETH_MIN_MTU; ndev->min_mtu = ETH_MIN_MTU;
...@@ -2697,7 +2781,7 @@ static int ravb_probe(struct platform_device *pdev) ...@@ -2697,7 +2781,7 @@ static int ravb_probe(struct platform_device *pdev)
/* Set GTI value */ /* Set GTI value */
error = ravb_set_gti(ndev); error = ravb_set_gti(ndev);
if (error) if (error)
goto out_disable_refclk; goto out_disable_gptp_clk;
/* Request GTI loading */ /* Request GTI loading */
ravb_modify(ndev, GCCR, GCCR_LTI, GCCR_LTI); ravb_modify(ndev, GCCR, GCCR_LTI, GCCR_LTI);
...@@ -2717,7 +2801,7 @@ static int ravb_probe(struct platform_device *pdev) ...@@ -2717,7 +2801,7 @@ static int ravb_probe(struct platform_device *pdev)
"Cannot allocate desc base address table (size %d bytes)\n", "Cannot allocate desc base address table (size %d bytes)\n",
priv->desc_bat_size); priv->desc_bat_size);
error = -ENOMEM; error = -ENOMEM;
goto out_disable_refclk; goto out_disable_gptp_clk;
} }
for (q = RAVB_BE; q < DBAT_ENTRY_NUM; q++) for (q = RAVB_BE; q < DBAT_ENTRY_NUM; q++)
priv->desc_bat[q].die_dt = DT_EOS; priv->desc_bat[q].die_dt = DT_EOS;
...@@ -2780,6 +2864,8 @@ static int ravb_probe(struct platform_device *pdev) ...@@ -2780,6 +2864,8 @@ static int ravb_probe(struct platform_device *pdev)
/* Stop PTP Clock driver */ /* Stop PTP Clock driver */
if (info->ccc_gac) if (info->ccc_gac)
ravb_ptp_stop(ndev); ravb_ptp_stop(ndev);
out_disable_gptp_clk:
clk_disable_unprepare(priv->gptp_clk);
out_disable_refclk: out_disable_refclk:
clk_disable_unprepare(priv->refclk); clk_disable_unprepare(priv->refclk);
out_release: out_release:
...@@ -2801,6 +2887,7 @@ static int ravb_remove(struct platform_device *pdev) ...@@ -2801,6 +2887,7 @@ static int ravb_remove(struct platform_device *pdev)
if (info->ccc_gac) if (info->ccc_gac)
ravb_ptp_stop(ndev); ravb_ptp_stop(ndev);
clk_disable_unprepare(priv->gptp_clk);
clk_disable_unprepare(priv->refclk); clk_disable_unprepare(priv->refclk);
dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat, dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat,
......
...@@ -198,7 +198,7 @@ static int ravb_ptp_extts(struct ptp_clock_info *ptp, ...@@ -198,7 +198,7 @@ static int ravb_ptp_extts(struct ptp_clock_info *ptp,
priv->ptp.extts[req->index] = on; priv->ptp.extts[req->index] = on;
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
if (!info->multi_irqs) if (!info->irq_en_dis)
ravb_modify(ndev, GIC, GIC_PTCE, on ? GIC_PTCE : 0); ravb_modify(ndev, GIC, GIC_PTCE, on ? GIC_PTCE : 0);
else if (on) else if (on)
ravb_write(ndev, GIE_PTCS, GIE); ravb_write(ndev, GIE_PTCS, GIE);
...@@ -254,7 +254,7 @@ static int ravb_ptp_perout(struct ptp_clock_info *ptp, ...@@ -254,7 +254,7 @@ static int ravb_ptp_perout(struct ptp_clock_info *ptp,
error = ravb_ptp_update_compare(priv, (u32)start_ns); error = ravb_ptp_update_compare(priv, (u32)start_ns);
if (!error) { if (!error) {
/* Unmask interrupt */ /* Unmask interrupt */
if (!info->multi_irqs) if (!info->irq_en_dis)
ravb_modify(ndev, GIC, GIC_PTME, GIC_PTME); ravb_modify(ndev, GIC, GIC_PTME, GIC_PTME);
else else
ravb_write(ndev, GIE_PTMS0, GIE); ravb_write(ndev, GIE_PTMS0, GIE);
...@@ -266,7 +266,7 @@ static int ravb_ptp_perout(struct ptp_clock_info *ptp, ...@@ -266,7 +266,7 @@ static int ravb_ptp_perout(struct ptp_clock_info *ptp,
perout->period = 0; perout->period = 0;
/* Mask interrupt */ /* Mask interrupt */
if (!info->multi_irqs) if (!info->irq_en_dis)
ravb_modify(ndev, GIC, GIC_PTME, 0); ravb_modify(ndev, GIC, GIC_PTME, 0);
else else
ravb_write(ndev, GID_PTMD0, GID); ravb_write(ndev, GID_PTMD0, GID);
......
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