mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
Merge branch 'ravb-add-gptp-support-for-gen4'
Niklas Söderlund says: ==================== ravb: Add gPTP support for Gen4 This series is the second part cleaning up how PTP timer support is implemented on R-Car Gen4. Currently there is partial support for it in some of the Ethernet devices that can use it, but not all. On Gen2 and Gen3 each RAVB instance have it's own private PTP clock as part of the RAVB register space. For this reason the PTP functionally was implemented directly in the RAVB driver. For Gen4 however there is a system-wide PTP clock shared by all RAVB instances, and on some Gen4 platforms with other Ethernet devices. The RAVB Gen4 driver currently advertise PTP support to user-space, but the support is in fact completely broken. It tries to use RAVB private PTP clock, which do not exist on Gen4. Further more the PTP clock behaved slightly different on Gen2 and Gen3. These differences have been handled by adding platform specific flags inside the driver. The usage of these flags have grown organically and been extended all over the driver as it gained new features. Adding a new third set of flags for Gen4 would be messy and add to the confusion. Therefore patches 1/10 thru 8/10 refactors the usage of the PTP flags into optional callbacks and untangles the usage. This allows adding Gen4 support easy as it can just implement it's own set of Gen4 specific callbacks without altering the driver logic. Patch 9/10 is a small DT binding addition adding an optional phandle to link a RAVB device to the external PTP clock. Ideally this property should be mandatory, but for backward comp ability is is made optional. If the phandle is not set, or the PTP clock not enabled, the RAVB driver will continue to faction as before, but no longer advertise PTP support to user space. Finally patch 10/10 adds the Gen4 specific PTP callbacks which allows the driver to use the external PTP clock. For part one of this work see [1]. The two series are independent of each other but both are needed before a third series liking the RAVB to the PTP clock in the platforms device tree. I will hold posting the third series until all dependencies are merged. For this reason there is no user of the new renesas,gptp device tree property added in this series. The work is tested on both Gen3 and Gen4 R-Car devices (with [1] and appropriate DTS). I do however not have access to any Gen2 device where the RAVB IP is wired to a MAC, so the small rework of the flags for Gen2 to callbacks have only been compiled tested. If anybody have a RZ device where RAVB is wired and uses the Gen2 method of starting/stopping the PTP timer together with the DMAC please test this. [1] https://lore.kernel.org/20260803095232.3527111-1-niklas.soderlund+renesas@ragnatech.se/ ==================== Link: https://patch.msgid.link/20260921175037.4084310-1-niklas.soderlund+renesas@ragnatech.se Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
e3a46dde23
|
|
@ -97,6 +97,8 @@ properties:
|
|||
|
||||
phy-handle: true
|
||||
|
||||
ptp-timer: true
|
||||
|
||||
'#address-cells':
|
||||
description: Number of address cells for the MDIO bus.
|
||||
const: 1
|
||||
|
|
@ -305,6 +307,15 @@ allOf:
|
|||
items:
|
||||
- const: fck
|
||||
- const: refclk
|
||||
- if:
|
||||
not:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: renesas,etheravb-rcar-gen4
|
||||
then:
|
||||
properties:
|
||||
ptp-timer: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
|
|
|
|||
|
|
@ -249,6 +249,8 @@ enum APSR_BIT {
|
|||
APSR_RDM = 0x00002000,
|
||||
APSR_TDM = 0x00004000,
|
||||
APSR_MIISELECT = 0x01000000, /* R-Car V4M only */
|
||||
APSR_GPTPTIMER_SOURCE = BIT(25), /* Gen4 */
|
||||
APSR_GPTPCLOCK = BIT(29), /* Gen4 */
|
||||
};
|
||||
|
||||
/* RCR */
|
||||
|
|
@ -1028,13 +1030,37 @@ struct ravb_ptp_perout {
|
|||
struct ravb_ptp {
|
||||
struct ptp_clock *clock;
|
||||
struct ptp_clock_info info;
|
||||
int phc_index;
|
||||
u32 default_addend;
|
||||
u32 current_addend;
|
||||
int extts[N_EXT_TS];
|
||||
struct ravb_ptp_perout perout[N_PER_OUT];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ravb_gptp_info - Platform specific gPTP behavior
|
||||
*
|
||||
* Each generation of RAVB have slightly different behaviors when interacting
|
||||
* with the gPTP clock. This struct provides the callbacks to be called at
|
||||
* critical points in the RAVB driver.
|
||||
*
|
||||
* @probe: Probe the gPTP clock
|
||||
* @clock_index: Get the PTP clock index, if any
|
||||
* @set_config_mode: Enter config mode
|
||||
* @dmac_start: Called when the DMAC starts
|
||||
* @dmac_stop: Called when the DMAC stops
|
||||
* @ndev_open: Called when the ndev is opened
|
||||
* @ndev_close: Called when the ndev is closed
|
||||
*/
|
||||
struct ravb_gptp_info {
|
||||
int (*probe)(struct net_device *ndev);
|
||||
int (*clock_index)(struct net_device *ndev);
|
||||
int (*set_config_mode)(struct net_device *ndev);
|
||||
int (*dmac_start)(struct net_device *ndev);
|
||||
void (*dmac_stop)(struct net_device *ndev);
|
||||
int (*ndev_open)(struct net_device *ndev);
|
||||
void (*ndev_close)(struct net_device *ndev);
|
||||
};
|
||||
|
||||
struct ravb_hw_info {
|
||||
int (*receive)(struct net_device *ndev, int budget, int q);
|
||||
void (*set_rate)(struct net_device *ndev);
|
||||
|
|
@ -1053,6 +1079,7 @@ struct ravb_hw_info {
|
|||
u32 rx_buffer_size;
|
||||
u32 rx_desc_size;
|
||||
u32 dbat_entry_num;
|
||||
const struct ravb_gptp_info *ptp; /* Callbacks to handle gPTP interactions. */
|
||||
unsigned aligned_tx: 1;
|
||||
unsigned coalesce_irqs:1; /* Needs software IRQ coalescing */
|
||||
|
||||
|
|
@ -1063,9 +1090,6 @@ struct ravb_hw_info {
|
|||
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 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 magic_pkt:1; /* E-MAC supports magic packet detection */
|
||||
unsigned half_duplex:1; /* E-MAC supports half duplex mode */
|
||||
|
|
@ -1110,6 +1134,7 @@ struct ravb_private {
|
|||
struct list_head ts_skb_list;
|
||||
u32 ts_skb_tag;
|
||||
struct ravb_ptp ptp;
|
||||
struct device_node *of_gptp; /* Reference to external gPTP clock, if any. */
|
||||
spinlock_t lock; /* Register access lock */
|
||||
u32 cur_rx[NUM_RX_QUEUE]; /* Consumer ring indices */
|
||||
u32 dirty_rx[NUM_RX_QUEUE]; /* Producer ring indices */
|
||||
|
|
@ -1163,7 +1188,7 @@ void ravb_modify(struct net_device *ndev, enum ravb_reg reg, u32 clear,
|
|||
int ravb_wait(struct net_device *ndev, enum ravb_reg reg, u32 mask, u32 value);
|
||||
|
||||
void ravb_ptp_interrupt(struct net_device *ndev);
|
||||
void ravb_ptp_init(struct net_device *ndev, struct platform_device *pdev);
|
||||
int ravb_ptp_init(struct net_device *ndev);
|
||||
void ravb_ptp_stop(struct net_device *ndev);
|
||||
|
||||
#endif /* #ifndef __RAVB_H__ */
|
||||
|
|
|
|||
|
|
@ -707,7 +707,15 @@ static int ravb_dmac_init(struct net_device *ndev)
|
|||
return error;
|
||||
|
||||
/* Setting the control will start the AVB-DMAC process. */
|
||||
return ravb_set_opmode(ndev, CCC_OPC_OPERATION);
|
||||
error = ravb_set_opmode(ndev, CCC_OPC_OPERATION);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* Initialise PTP Clock driver */
|
||||
if (info->ptp && info->ptp->dmac_start)
|
||||
return info->ptp->dmac_start(ndev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ravb_get_tx_tstamp(struct net_device *ndev)
|
||||
|
|
@ -1115,6 +1123,10 @@ static int ravb_stop_dma(struct net_device *ndev)
|
|||
netdev_err(ndev, "failed to stop AXI BUS\n");
|
||||
}
|
||||
|
||||
/* Stop PTP Clock driver */
|
||||
if (info->ptp && info->ptp->dmac_stop)
|
||||
info->ptp->dmac_stop(ndev);
|
||||
|
||||
/* Stop AVB-DMAC process */
|
||||
return ravb_set_opmode(ndev, CCC_OPC_CONFIG);
|
||||
}
|
||||
|
|
@ -1719,9 +1731,7 @@ static int ravb_set_ringparam(struct net_device *ndev,
|
|||
|
||||
if (netif_running(ndev)) {
|
||||
netif_device_detach(ndev);
|
||||
/* Stop PTP Clock driver */
|
||||
if (info->gptp)
|
||||
ravb_ptp_stop(ndev);
|
||||
|
||||
/* Wait for DMA stopping */
|
||||
error = ravb_stop_dma(ndev);
|
||||
if (error) {
|
||||
|
|
@ -1752,10 +1762,6 @@ static int ravb_set_ringparam(struct net_device *ndev,
|
|||
|
||||
ravb_emac_init(ndev);
|
||||
|
||||
/* Initialise PTP Clock driver */
|
||||
if (info->gptp)
|
||||
ravb_ptp_init(ndev, priv->pdev);
|
||||
|
||||
netif_device_attach(ndev);
|
||||
}
|
||||
|
||||
|
|
@ -1767,8 +1773,13 @@ static int ravb_get_ts_info(struct net_device *ndev,
|
|||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
const struct ravb_hw_info *hw_info = priv->info;
|
||||
int index = -1;
|
||||
|
||||
if (hw_info->gptp || hw_info->ccc_gac) {
|
||||
if (hw_info->ptp && hw_info->ptp->clock_index)
|
||||
index = hw_info->ptp->clock_index(ndev);
|
||||
|
||||
/* Only advertise ptp clock if present. */
|
||||
if (index >= 0) {
|
||||
info->so_timestamping =
|
||||
SOF_TIMESTAMPING_TX_SOFTWARE |
|
||||
SOF_TIMESTAMPING_TX_HARDWARE |
|
||||
|
|
@ -1779,7 +1790,7 @@ static int ravb_get_ts_info(struct net_device *ndev,
|
|||
(1 << HWTSTAMP_FILTER_NONE) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
|
||||
(1 << HWTSTAMP_FILTER_ALL);
|
||||
info->phc_index = READ_ONCE(priv->ptp.phc_index);
|
||||
info->phc_index = index;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -1829,52 +1840,21 @@ static int ravb_set_config_mode(struct net_device *ndev)
|
|||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
const struct ravb_hw_info *info = priv->info;
|
||||
int error;
|
||||
|
||||
if (info->gptp) {
|
||||
error = ravb_set_opmode(ndev, CCC_OPC_CONFIG);
|
||||
if (error)
|
||||
return error;
|
||||
/* Set CSEL value */
|
||||
ravb_modify(ndev, CCC, CCC_CSEL, CCC_CSEL_HPB);
|
||||
} else if (info->ccc_gac) {
|
||||
error = ravb_set_opmode(ndev, CCC_OPC_CONFIG | CCC_GAC | CCC_CSEL_HPB);
|
||||
} else {
|
||||
error = ravb_set_opmode(ndev, CCC_OPC_CONFIG);
|
||||
}
|
||||
if (info->ptp && info->ptp->set_config_mode)
|
||||
return info->ptp->set_config_mode(ndev);
|
||||
|
||||
return error;
|
||||
return ravb_set_opmode(ndev, CCC_OPC_CONFIG);
|
||||
}
|
||||
|
||||
static void ravb_set_gti(struct net_device *ndev)
|
||||
static int ravb_compute_gti(struct net_device *ndev, struct clk *clk)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
const struct ravb_hw_info *info = priv->info;
|
||||
|
||||
if (!(info->gptp || info->ccc_gac))
|
||||
return;
|
||||
|
||||
ravb_write(ndev, priv->gti_tiv, GTI);
|
||||
|
||||
/* Request GTI loading */
|
||||
ravb_modify(ndev, GCCR, GCCR_LTI, GCCR_LTI);
|
||||
}
|
||||
|
||||
static int ravb_compute_gti(struct net_device *ndev)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
const struct ravb_hw_info *info = priv->info;
|
||||
struct device *dev = ndev->dev.parent;
|
||||
unsigned long rate;
|
||||
u64 inc;
|
||||
|
||||
if (!(info->gptp || info->ccc_gac))
|
||||
return 0;
|
||||
|
||||
if (info->gptp_ref_clk)
|
||||
rate = clk_get_rate(priv->gptp_clk);
|
||||
else
|
||||
rate = clk_get_rate(priv->clk);
|
||||
rate = clk_get_rate(clk);
|
||||
if (!rate)
|
||||
return -EINVAL;
|
||||
|
||||
|
|
@ -1974,11 +1954,12 @@ static int ravb_open(struct net_device *ndev)
|
|||
|
||||
ravb_emac_init(ndev);
|
||||
|
||||
ravb_set_gti(ndev);
|
||||
|
||||
/* Initialise PTP Clock driver */
|
||||
if (info->gptp || info->ccc_gac)
|
||||
ravb_ptp_init(ndev, priv->pdev);
|
||||
if (info->ptp && info->ptp->ndev_open) {
|
||||
error = info->ptp->ndev_open(ndev);
|
||||
if (error)
|
||||
goto out_ptp_stop;
|
||||
}
|
||||
|
||||
/* PHY control start */
|
||||
error = ravb_phy_start(ndev);
|
||||
|
|
@ -1991,8 +1972,8 @@ static int ravb_open(struct net_device *ndev)
|
|||
|
||||
out_ptp_stop:
|
||||
/* Stop PTP Clock driver */
|
||||
if (info->gptp || info->ccc_gac)
|
||||
ravb_ptp_stop(ndev);
|
||||
if (info->ptp && info->ptp->ndev_close)
|
||||
info->ptp->ndev_close(ndev);
|
||||
ravb_stop_dma(ndev);
|
||||
out_set_reset:
|
||||
ravb_set_opmode(ndev, CCC_OPC_RESET);
|
||||
|
|
@ -2036,10 +2017,6 @@ static void ravb_tx_timeout_work(struct work_struct *work)
|
|||
|
||||
netif_tx_stop_all_queues(ndev);
|
||||
|
||||
/* Stop PTP Clock driver */
|
||||
if (info->gptp)
|
||||
ravb_ptp_stop(ndev);
|
||||
|
||||
/* Wait for DMA stopping */
|
||||
if (ravb_stop_dma(ndev)) {
|
||||
/* If ravb_stop_dma() fails, the hardware is still operating
|
||||
|
|
@ -2072,10 +2049,6 @@ static void ravb_tx_timeout_work(struct work_struct *work)
|
|||
ravb_emac_init(ndev);
|
||||
|
||||
out:
|
||||
/* Initialise PTP Clock driver */
|
||||
if (info->gptp)
|
||||
ravb_ptp_init(ndev, priv->pdev);
|
||||
|
||||
netif_tx_start_all_queues(ndev);
|
||||
|
||||
out_unlock:
|
||||
|
|
@ -2208,7 +2181,7 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
|||
desc->dptr = cpu_to_le32(dma_addr);
|
||||
|
||||
/* TX timestamp required */
|
||||
if (info->gptp || info->ccc_gac) {
|
||||
if (info->ptp) {
|
||||
if (q == RAVB_NC) {
|
||||
ts_skb = kmalloc_obj(*ts_skb, GFP_ATOMIC);
|
||||
if (!ts_skb) {
|
||||
|
|
@ -2390,8 +2363,8 @@ static int ravb_close(struct net_device *ndev)
|
|||
}
|
||||
|
||||
/* Stop PTP Clock driver */
|
||||
if (info->gptp || info->ccc_gac)
|
||||
ravb_ptp_stop(ndev);
|
||||
if (info->ptp && info->ptp->ndev_close)
|
||||
info->ptp->ndev_close(ndev);
|
||||
|
||||
/* Set the config mode to stop the AVB-DMAC's processes */
|
||||
if (ravb_stop_dma(ndev) < 0)
|
||||
|
|
@ -2399,7 +2372,7 @@ static int ravb_close(struct net_device *ndev)
|
|||
"device will be stopped after h/w processes are done.\n");
|
||||
|
||||
/* Clear the timestamp list */
|
||||
if (info->gptp || info->ccc_gac) {
|
||||
if (info->ptp) {
|
||||
list_for_each_entry_safe(ts_skb, ts_skb2, &priv->ts_skb_list, list) {
|
||||
list_del(&ts_skb->list);
|
||||
kfree_skb(ts_skb->skb);
|
||||
|
|
@ -2681,6 +2654,45 @@ static int ravb_mdio_release(struct ravb_private *priv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ravb_gen2_ptp_probe(struct net_device *ndev)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
|
||||
return ravb_compute_gti(ndev, priv->clk);
|
||||
}
|
||||
|
||||
static int ravb_gen2_ptp_clock_index(struct net_device *ndev)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
|
||||
if (!priv->ptp.clock)
|
||||
return -ENODEV;
|
||||
|
||||
return ptp_clock_index(priv->ptp.clock);
|
||||
}
|
||||
|
||||
static int ravb_gen2_ptp_set_config_mode(struct net_device *ndev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ravb_set_opmode(ndev, CCC_OPC_CONFIG);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* gPTP Clock Select High-speed peripheral bus clock. */
|
||||
ravb_modify(ndev, CCC, CCC_CSEL, CCC_CSEL_HPB);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ravb_gptp_info ravb_gen2_ptp_info = {
|
||||
.probe = ravb_gen2_ptp_probe,
|
||||
.clock_index = ravb_gen2_ptp_clock_index,
|
||||
.set_config_mode = ravb_gen2_ptp_set_config_mode,
|
||||
.dmac_start = ravb_ptp_init,
|
||||
.dmac_stop = ravb_ptp_stop,
|
||||
};
|
||||
|
||||
static const struct ravb_hw_info ravb_gen2_hw_info = {
|
||||
.receive = ravb_rx_rcar,
|
||||
.set_rate = ravb_set_rate_rcar,
|
||||
|
|
@ -2699,12 +2711,26 @@ static const struct ravb_hw_info ravb_gen2_hw_info = {
|
|||
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)),
|
||||
.rx_desc_size = sizeof(struct ravb_ex_rx_desc),
|
||||
.dbat_entry_num = 22,
|
||||
.ptp = &ravb_gen2_ptp_info,
|
||||
.aligned_tx = 1,
|
||||
.gptp = 1,
|
||||
.nc_queues = 1,
|
||||
.magic_pkt = 1,
|
||||
};
|
||||
|
||||
static int ravb_gen3_ptp_set_config_mode(struct net_device *ndev)
|
||||
{
|
||||
/* Enable gPTP Clock and Select High-speed peripheral bus clock. */
|
||||
return ravb_set_opmode(ndev, CCC_OPC_CONFIG | CCC_GAC | CCC_CSEL_HPB);
|
||||
}
|
||||
|
||||
static const struct ravb_gptp_info ravb_gen3_ptp_info = {
|
||||
.probe = ravb_gen2_ptp_probe,
|
||||
.clock_index = ravb_gen2_ptp_clock_index,
|
||||
.set_config_mode = ravb_gen3_ptp_set_config_mode,
|
||||
.ndev_open = ravb_ptp_init,
|
||||
.ndev_close = ravb_ptp_stop,
|
||||
};
|
||||
|
||||
static const struct ravb_hw_info ravb_gen3_hw_info = {
|
||||
.receive = ravb_rx_rcar,
|
||||
.set_rate = ravb_set_rate_rcar,
|
||||
|
|
@ -2723,15 +2749,66 @@ static const struct ravb_hw_info ravb_gen3_hw_info = {
|
|||
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)),
|
||||
.rx_desc_size = sizeof(struct ravb_ex_rx_desc),
|
||||
.dbat_entry_num = 22,
|
||||
.ptp = &ravb_gen3_ptp_info,
|
||||
.internal_delay = 1,
|
||||
.tx_counters = 1,
|
||||
.multi_irqs = 1,
|
||||
.irq_en_dis = 1,
|
||||
.ccc_gac = 1,
|
||||
.nc_queues = 1,
|
||||
.magic_pkt = 1,
|
||||
};
|
||||
|
||||
static int ravb_gen4_ptp_probe(struct net_device *ndev)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
|
||||
priv->of_gptp = of_parse_phandle(priv->pdev->dev.of_node, "ptp-timer", 0);
|
||||
if (!priv->of_gptp)
|
||||
return 0;
|
||||
|
||||
if (!of_device_is_available(priv->of_gptp)) {
|
||||
of_node_put(priv->of_gptp);
|
||||
priv->of_gptp = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ravb_gen4_ptp_clock_index(struct net_device *ndev)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
|
||||
/* If no clock, mimic ptp_clock_index_by_of_node() fail and return -1 */
|
||||
if (!priv->of_gptp)
|
||||
return -1;
|
||||
|
||||
return ptp_clock_index_by_of_node(priv->of_gptp);
|
||||
}
|
||||
|
||||
static int ravb_gen4_ptp_set_config_mode(struct net_device *ndev)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
int ret;
|
||||
|
||||
/* Enable gPTP Clock and Select High-speed peripheral bus clock. */
|
||||
ret = ravb_set_opmode(ndev, CCC_OPC_CONFIG | CCC_GAC | CCC_CSEL_HPB);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Set PTP source to GPTP module, only option on Gen4. */
|
||||
if (priv->of_gptp)
|
||||
ravb_modify(ndev, APSR, APSR_GPTPTIMER_SOURCE | APSR_GPTPCLOCK,
|
||||
APSR_GPTPTIMER_SOURCE | APSR_GPTPCLOCK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ravb_gptp_info ravb_gen4_ptp_info = {
|
||||
.probe = ravb_gen4_ptp_probe,
|
||||
.clock_index = ravb_gen4_ptp_clock_index,
|
||||
.set_config_mode = ravb_gen4_ptp_set_config_mode,
|
||||
};
|
||||
|
||||
static const struct ravb_hw_info ravb_gen4_hw_info = {
|
||||
.receive = ravb_rx_rcar,
|
||||
.set_rate = ravb_set_rate_rcar,
|
||||
|
|
@ -2754,11 +2831,30 @@ static const struct ravb_hw_info ravb_gen4_hw_info = {
|
|||
.tx_counters = 1,
|
||||
.multi_irqs = 1,
|
||||
.irq_en_dis = 1,
|
||||
.ccc_gac = 1,
|
||||
.ptp = &ravb_gen4_ptp_info,
|
||||
.nc_queues = 1,
|
||||
.magic_pkt = 1,
|
||||
};
|
||||
|
||||
static int ravb_rzv2m_ptp_probe(struct net_device *ndev)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
|
||||
priv->gptp_clk = devm_clk_get(&priv->pdev->dev, "gptp");
|
||||
if (IS_ERR(priv->gptp_clk))
|
||||
return PTR_ERR(priv->gptp_clk);
|
||||
|
||||
return ravb_compute_gti(ndev, priv->gptp_clk);
|
||||
}
|
||||
|
||||
static const struct ravb_gptp_info ravb_rzv2m_ptp_info = {
|
||||
.probe = ravb_rzv2m_ptp_probe,
|
||||
.clock_index = ravb_gen2_ptp_clock_index,
|
||||
.set_config_mode = ravb_gen2_ptp_set_config_mode,
|
||||
.dmac_start = ravb_ptp_init,
|
||||
.dmac_stop = ravb_ptp_stop,
|
||||
};
|
||||
|
||||
static const struct ravb_hw_info ravb_rzv2m_hw_info = {
|
||||
.receive = ravb_rx_rcar,
|
||||
.set_rate = ravb_set_rate_rcar,
|
||||
|
|
@ -2779,8 +2875,7 @@ static const struct ravb_hw_info ravb_rzv2m_hw_info = {
|
|||
.dbat_entry_num = 22,
|
||||
.multi_irqs = 1,
|
||||
.err_mgmt_irqs = 1,
|
||||
.gptp = 1,
|
||||
.gptp_ref_clk = 1,
|
||||
.ptp = &ravb_rzv2m_ptp_info,
|
||||
.nc_queues = 1,
|
||||
.magic_pkt = 1,
|
||||
};
|
||||
|
|
@ -2955,7 +3050,6 @@ static int ravb_probe(struct platform_device *pdev)
|
|||
priv->rstc = rstc;
|
||||
priv->ndev = ndev;
|
||||
priv->pdev = pdev;
|
||||
priv->ptp.phc_index = -1;
|
||||
priv->num_tx_ring[RAVB_BE] = BE_TX_RING_SIZE;
|
||||
priv->num_rx_ring[RAVB_BE] = BE_RX_RING_SIZE;
|
||||
if (info->nc_queues) {
|
||||
|
|
@ -2973,12 +3067,10 @@ static int ravb_probe(struct platform_device *pdev)
|
|||
goto out_reset_assert;
|
||||
}
|
||||
|
||||
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);
|
||||
if (info->ptp && info->ptp->probe) {
|
||||
error = info->ptp->probe(ndev);
|
||||
if (error)
|
||||
goto out_reset_assert;
|
||||
}
|
||||
}
|
||||
|
||||
priv->refclk = devm_clk_get_optional(&pdev->dev, "refclk");
|
||||
|
|
@ -3031,10 +3123,6 @@ static int ravb_probe(struct platform_device *pdev)
|
|||
ndev->netdev_ops = &ravb_netdev_ops;
|
||||
ndev->ethtool_ops = &ravb_ethtool_ops;
|
||||
|
||||
error = ravb_compute_gti(ndev);
|
||||
if (error)
|
||||
goto out_rpm_put;
|
||||
|
||||
ravb_parse_delay_mode(np, ndev);
|
||||
|
||||
/* Allocate descriptor base address table */
|
||||
|
|
@ -3157,6 +3245,7 @@ static void ravb_remove(struct platform_device *pdev)
|
|||
pm_runtime_disable(&pdev->dev);
|
||||
pm_runtime_dont_use_autosuspend(dev);
|
||||
clk_unprepare(priv->refclk);
|
||||
of_node_put(priv->of_gptp);
|
||||
reset_control_assert(priv->rstc);
|
||||
free_netdev(ndev);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
|
@ -3182,9 +3271,6 @@ static int ravb_wol_setup(struct net_device *ndev)
|
|||
/* Enable MagicPacket */
|
||||
ravb_modify(ndev, ECMR, ECMR_MPDE, ECMR_MPDE);
|
||||
|
||||
if (priv->info->ccc_gac)
|
||||
ravb_ptp_stop(ndev);
|
||||
|
||||
return enable_irq_wake(priv->emac_irq);
|
||||
}
|
||||
|
||||
|
|
@ -3204,9 +3290,6 @@ static int ravb_wol_restore(struct net_device *ndev)
|
|||
if (error)
|
||||
return error;
|
||||
|
||||
if (priv->info->ccc_gac)
|
||||
ravb_ptp_init(ndev, priv->pdev);
|
||||
|
||||
if (info->nc_queues)
|
||||
napi_enable(&priv->napi[RAVB_NC]);
|
||||
napi_enable(&priv->napi[RAVB_BE]);
|
||||
|
|
|
|||
|
|
@ -313,31 +313,39 @@ void ravb_ptp_interrupt(struct net_device *ndev)
|
|||
ravb_write(ndev, ~(gis | GIS_RESERVED), GIS);
|
||||
}
|
||||
|
||||
void ravb_ptp_init(struct net_device *ndev, struct platform_device *pdev)
|
||||
int ravb_ptp_init(struct net_device *ndev)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
struct ptp_clock *clock;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
priv->ptp.info = ravb_ptp_info;
|
||||
|
||||
priv->ptp.default_addend = ravb_read(ndev, GTI);
|
||||
priv->ptp.default_addend = priv->gti_tiv;
|
||||
priv->ptp.current_addend = priv->ptp.default_addend;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
/* Set gPTP Timer Increment Value. */
|
||||
ravb_write(ndev, priv->ptp.default_addend, GTI);
|
||||
|
||||
/* Request GTI loading. */
|
||||
ravb_modify(ndev, GCCR, GCCR_LTI, GCCR_LTI);
|
||||
|
||||
/* Wait for GIT loading to complete by checking there are no requests. */
|
||||
ravb_wait(ndev, GCCR, GCCR_TCR, GCCR_TCR_NOREQ);
|
||||
|
||||
ravb_modify(ndev, GCCR, GCCR_TCSS, GCCR_TCSS_ADJGPTP);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
clock = ptp_clock_register(&priv->ptp.info, &pdev->dev);
|
||||
if (IS_ERR(clock)) {
|
||||
netdev_err(ndev, "failed to register PTP clock: %pe\n", clock);
|
||||
clock = NULL;
|
||||
priv->ptp.clock = ptp_clock_register(&priv->ptp.info, &priv->pdev->dev);
|
||||
if (IS_ERR(priv->ptp.clock)) {
|
||||
ret = PTR_ERR(priv->ptp.clock);
|
||||
priv->ptp.clock = NULL;
|
||||
ravb_ptp_stop(ndev);
|
||||
}
|
||||
|
||||
WRITE_ONCE(priv->ptp.clock, clock);
|
||||
if (clock)
|
||||
WRITE_ONCE(priv->ptp.phc_index, ptp_clock_index(clock));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ravb_ptp_disable(struct net_device *ndev)
|
||||
|
|
@ -360,14 +368,12 @@ static void ravb_ptp_sync_irqs(struct net_device *ndev)
|
|||
void ravb_ptp_stop(struct net_device *ndev)
|
||||
{
|
||||
struct ravb_private *priv = netdev_priv(ndev);
|
||||
struct ptp_clock *clock;
|
||||
|
||||
WRITE_ONCE(priv->ptp.phc_index, -1);
|
||||
clock = xchg(&priv->ptp.clock, NULL);
|
||||
|
||||
ravb_ptp_disable(ndev);
|
||||
ravb_ptp_sync_irqs(ndev);
|
||||
|
||||
if (clock)
|
||||
ptp_clock_unregister(clock);
|
||||
if (priv->ptp.clock) {
|
||||
ptp_clock_unregister(priv->ptp.clock);
|
||||
priv->ptp.clock = NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user