Skip to content

Commit

Permalink
Renesas Ethernet AVB PTP clock driver
Browse files Browse the repository at this point in the history
Ethernet AVB device includes the gPTP  timer, so we can implement a PTP clock
driver.  We're doing that in a separate file, with  the main Ethernet driver
calling the PTP driver's [de]initialization and interrupt handler functions.
Unfortunately, the clock seems tightly coupled with the AVB-DMAC, so when that
one leaves the operation mode, we have to unregister the PTP clock... :-(

Based on the original patches by Masaru Nagai.

Signed-off-by: Masaru Nagai <masaru.nagai.vx@renesas.com>
Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Sergei Shtylyov authored and David S. Miller committed Jun 11, 2015
1 parent c156633 commit a0d2f20
Show file tree
Hide file tree
Showing 4 changed files with 414 additions and 5 deletions.
3 changes: 3 additions & 0 deletions drivers/net/ethernet/renesas/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@
#

obj-$(CONFIG_SH_ETH) += sh_eth.o

ravb-objs := ravb_main.o ravb_ptp.o

obj-$(CONFIG_RAVB) += ravb.o
26 changes: 26 additions & 0 deletions drivers/net/ethernet/renesas/ravb.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include <linux/mdio-bitbang.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
#include <linux/platform_device.h>
#include <linux/ptp_clock_kernel.h>

#define BE_TX_RING_SIZE 64 /* TX ring size for Best Effort */
#define BE_RX_RING_SIZE 1024 /* RX ring size for Best Effort */
Expand Down Expand Up @@ -744,6 +746,23 @@ struct ravb_tstamp_skb {
u16 tag;
};

struct ravb_ptp_perout {
u32 target;
u32 period;
};

#define N_EXT_TS 1
#define N_PER_OUT 1

struct ravb_ptp {
struct ptp_clock *clock;
struct ptp_clock_info info;
u32 default_addend;
u32 current_addend;
int extts[N_EXT_TS];
struct ravb_ptp_perout perout[N_PER_OUT];
};

struct ravb_private {
struct net_device *ndev;
struct platform_device *pdev;
Expand All @@ -768,6 +787,7 @@ struct ravb_private {
u32 tstamp_rx_ctrl;
struct list_head ts_skb_list;
u32 ts_skb_tag;
struct ravb_ptp ptp;
spinlock_t lock; /* Register access lock */
u32 cur_rx[NUM_RX_QUEUE]; /* Consumer ring indices */
u32 dirty_rx[NUM_RX_QUEUE]; /* Producer ring indices */
Expand Down Expand Up @@ -803,4 +823,10 @@ static inline void ravb_write(struct net_device *ndev, u32 data,
iowrite32(data, priv->addr + reg);
}

int ravb_wait(struct net_device *ndev, enum ravb_reg reg, u32 mask, u32 value);

irqreturn_t ravb_ptp_interrupt(struct net_device *ndev);
void ravb_ptp_init(struct net_device *ndev, struct platform_device *pdev);
void ravb_ptp_stop(struct net_device *ndev);

#endif /* #ifndef __RAVB_H__ */
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
#include <linux/of_irq.h>
#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
Expand All @@ -41,8 +40,7 @@
NETIF_MSG_RX_ERR | \
NETIF_MSG_TX_ERR)

static int ravb_wait(struct net_device *ndev, enum ravb_reg reg, u32 mask,
u32 value)
int ravb_wait(struct net_device *ndev, enum ravb_reg reg, u32 mask, u32 value)
{
int i;

Expand Down Expand Up @@ -763,6 +761,9 @@ static irqreturn_t ravb_interrupt(int irq, void *dev_id)
result = IRQ_HANDLED;
}

if (iss & ISS_CGIS)
result = ravb_ptp_interrupt(ndev);

mmiowb();
spin_unlock(&priv->lock);
return result;
Expand Down Expand Up @@ -1103,6 +1104,8 @@ static int ravb_set_ringparam(struct net_device *ndev,

if (netif_running(ndev)) {
netif_device_detach(ndev);
/* Stop PTP Clock driver */
ravb_ptp_stop(ndev);
/* Wait for DMA stopping */
error = ravb_stop_dma(ndev);
if (error) {
Expand Down Expand Up @@ -1132,6 +1135,9 @@ static int ravb_set_ringparam(struct net_device *ndev,

ravb_emac_init(ndev);

/* Initialise PTP Clock driver */
ravb_ptp_init(ndev, priv->pdev);

netif_device_attach(ndev);
}

Expand All @@ -1141,6 +1147,8 @@ static int ravb_set_ringparam(struct net_device *ndev,
static int ravb_get_ts_info(struct net_device *ndev,
struct ethtool_ts_info *info)
{
struct ravb_private *priv = netdev_priv(ndev);

info->so_timestamping =
SOF_TIMESTAMPING_TX_SOFTWARE |
SOF_TIMESTAMPING_RX_SOFTWARE |
Expand All @@ -1153,7 +1161,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 = -1;
info->phc_index = ptp_clock_index(priv->ptp.clock);

return 0;
}
Expand Down Expand Up @@ -1195,15 +1203,21 @@ static int ravb_open(struct net_device *ndev)
goto out_free_irq;
ravb_emac_init(ndev);

/* Initialise PTP Clock driver */
ravb_ptp_init(ndev, priv->pdev);

netif_tx_start_all_queues(ndev);

/* PHY control start */
error = ravb_phy_start(ndev);
if (error)
goto out_free_irq;
goto out_ptp_stop;

return 0;

out_ptp_stop:
/* Stop PTP Clock driver */
ravb_ptp_stop(ndev);
out_free_irq:
free_irq(ndev->irq, ndev);
out_napi_off:
Expand Down Expand Up @@ -1235,6 +1249,9 @@ static void ravb_tx_timeout_work(struct work_struct *work)

netif_tx_stop_all_queues(ndev);

/* Stop PTP Clock driver */
ravb_ptp_stop(ndev);

/* Wait for DMA stopping */
ravb_stop_dma(ndev);

Expand All @@ -1245,6 +1262,9 @@ static void ravb_tx_timeout_work(struct work_struct *work)
ravb_dmac_init(ndev);
ravb_emac_init(ndev);

/* Initialise PTP Clock driver */
ravb_ptp_init(ndev, priv->pdev);

netif_tx_start_all_queues(ndev);
}

Expand Down Expand Up @@ -1409,6 +1429,9 @@ static int ravb_close(struct net_device *ndev)
ravb_write(ndev, 0, RIC2);
ravb_write(ndev, 0, TIC);

/* Stop PTP Clock driver */
ravb_ptp_stop(ndev);

/* Set the config mode to stop the AVB-DMAC's processes */
if (ravb_stop_dma(ndev) < 0)
netdev_err(ndev,
Expand Down
Loading

0 comments on commit a0d2f20

Please sign in to comment.