linux/drivers/net/dsa/sja1105/sja1105_ptp.h
Vladimir Oltean 664277781c net: dsa: sja1105: Change the PTP command access pattern
The PTP command register contains enable bits for:
- Putting the 64-bit PTPCLKVAL register in add/subtract or write mode
- Taking timestamps off of the corrected vs free-running clock
- Starting/stopping the TTEthernet scheduling
- Starting/stopping PPS output
- Resetting the switch

When a command needs to be issued (e.g. "change the PTPCLKVAL from write
mode to add/subtract mode"), one cannot simply write to the command
register setting the PTPCLKADD bit to 1, because that would zeroize the
other settings. One also cannot do a read-modify-write (that would be
too easy for this hardware) because not all bits of the command register
are readable over SPI.

So this leaves us with the only option of keeping the value of the PTP
command register in the driver, and operating on that.

Actually there are 2 types of PTP operations now:
- Operations that modify the cached PTP command. These operate on
  ptp_data->cmd as a pointer.
- Operations that apply all previously cached PTP settings, but don't
  otherwise cache what they did themselves. The sja1105_ptp_reset
  function is such an example. It copies the ptp_data->cmd on stack
  before modifying and writing it to SPI.

This practically means that struct sja1105_ptp_cmd is no longer an
implementation detail, since it needs to be stored in full into struct
sja1105_ptp_data, and hence in struct sja1105_private. So the (*ptp_cmd)
function prototype can change and take struct sja1105_ptp_cmd as second
argument now.

Signed-off-by: Vladimir Oltean <olteanv@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-10-14 16:45:40 -07:00

101 lines
2.4 KiB
C

/* SPDX-License-Identifier: GPL-2.0
* Copyright (c) 2019, Vladimir Oltean <olteanv@gmail.com>
*/
#ifndef _SJA1105_PTP_H
#define _SJA1105_PTP_H
#if IS_ENABLED(CONFIG_NET_DSA_SJA1105_PTP)
struct sja1105_ptp_cmd {
u64 resptp; /* reset */
};
struct sja1105_ptp_data {
struct ptp_clock_info caps;
struct ptp_clock *clock;
struct sja1105_ptp_cmd cmd;
/* The cycle counter translates the PTP timestamps (based on
* a free-running counter) into a software time domain.
*/
struct cyclecounter tstamp_cc;
struct timecounter tstamp_tc;
struct delayed_work refresh_work;
/* Serializes all operations on the cycle counter */
struct mutex lock;
};
int sja1105_ptp_clock_register(struct dsa_switch *ds);
void sja1105_ptp_clock_unregister(struct dsa_switch *ds);
int sja1105et_ptp_cmd(const struct dsa_switch *ds,
const struct sja1105_ptp_cmd *cmd);
int sja1105pqrs_ptp_cmd(const struct dsa_switch *ds,
const struct sja1105_ptp_cmd *cmd);
int sja1105_get_ts_info(struct dsa_switch *ds, int port,
struct ethtool_ts_info *ts);
void sja1105_ptp_txtstamp_skb(struct dsa_switch *ds, int slot,
struct sk_buff *clone);
int sja1105_ptp_reset(struct dsa_switch *ds);
bool sja1105_port_rxtstamp(struct dsa_switch *ds, int port,
struct sk_buff *skb, unsigned int type);
bool sja1105_port_txtstamp(struct dsa_switch *ds, int port,
struct sk_buff *skb, unsigned int type);
int sja1105_hwtstamp_get(struct dsa_switch *ds, int port, struct ifreq *ifr);
int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr);
#else
struct sja1105_ptp_cmd;
/* Structures cannot be empty in C. Bah!
* Keep the mutex as the only element, which is a bit more difficult to
* refactor out of sja1105_main.c anyway.
*/
struct sja1105_ptp_data {
struct mutex lock;
};
static inline int sja1105_ptp_clock_register(struct dsa_switch *ds)
{
return 0;
}
static inline void sja1105_ptp_clock_unregister(struct dsa_switch *ds) { }
static inline void sja1105_ptp_txtstamp_skb(struct dsa_switch *ds, int slot,
struct sk_buff *clone)
{
}
static inline int sja1105_ptp_reset(struct dsa_switch *ds)
{
return 0;
}
#define sja1105et_ptp_cmd NULL
#define sja1105pqrs_ptp_cmd NULL
#define sja1105_get_ts_info NULL
#define sja1105_port_rxtstamp NULL
#define sja1105_port_txtstamp NULL
#define sja1105_hwtstamp_get NULL
#define sja1105_hwtstamp_set NULL
#endif /* IS_ENABLED(CONFIG_NET_DSA_SJA1105_PTP) */
#endif /* _SJA1105_PTP_H */