mirror of https://gitee.com/openkylin/linux.git
Merge branch 'PTP-support-for-mv88e6165-family'
Andrew Lunn says: ==================== PTP support for mv88e6165 family The mv88e6165 family of switches supports PTP. It is however not fully compatible with the current PTP support in the mv88e6xxx driver. This patchset adds a level of abstraction to the PTP code, and then adds the code needed to support the mv88e6165 family. v2: Correctly cluster local variables in mv88e6xxx_ptp_setup() Added Acked-by: Richard Cochran <richardcochran@gmail.com> ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
14260e9170
|
@ -2810,6 +2810,8 @@ static const struct mv88e6xxx_ops mv88e6161_ops = {
|
|||
.reset = mv88e6352_g1_reset,
|
||||
.vtu_getnext = mv88e6352_g1_vtu_getnext,
|
||||
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
|
||||
.avb_ops = &mv88e6165_avb_ops,
|
||||
.ptp_ops = &mv88e6165_ptp_ops,
|
||||
};
|
||||
|
||||
static const struct mv88e6xxx_ops mv88e6165_ops = {
|
||||
|
@ -2838,6 +2840,8 @@ static const struct mv88e6xxx_ops mv88e6165_ops = {
|
|||
.reset = mv88e6352_g1_reset,
|
||||
.vtu_getnext = mv88e6352_g1_vtu_getnext,
|
||||
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
|
||||
.avb_ops = &mv88e6165_avb_ops,
|
||||
.ptp_ops = &mv88e6165_ptp_ops,
|
||||
};
|
||||
|
||||
static const struct mv88e6xxx_ops mv88e6171_ops = {
|
||||
|
@ -3134,6 +3138,8 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
|
|||
.vtu_getnext = mv88e6390_g1_vtu_getnext,
|
||||
.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
|
||||
.serdes_power = mv88e6390_serdes_power,
|
||||
.avb_ops = &mv88e6390_avb_ops,
|
||||
.ptp_ops = &mv88e6352_ptp_ops,
|
||||
};
|
||||
|
||||
static const struct mv88e6xxx_ops mv88e6240_ops = {
|
||||
|
@ -3176,6 +3182,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
|
|||
.serdes_power = mv88e6352_serdes_power,
|
||||
.gpio_ops = &mv88e6352_gpio_ops,
|
||||
.avb_ops = &mv88e6352_avb_ops,
|
||||
.ptp_ops = &mv88e6352_ptp_ops,
|
||||
};
|
||||
|
||||
static const struct mv88e6xxx_ops mv88e6290_ops = {
|
||||
|
@ -3215,6 +3222,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
|
|||
.serdes_power = mv88e6390_serdes_power,
|
||||
.gpio_ops = &mv88e6352_gpio_ops,
|
||||
.avb_ops = &mv88e6390_avb_ops,
|
||||
.ptp_ops = &mv88e6352_ptp_ops,
|
||||
};
|
||||
|
||||
static const struct mv88e6xxx_ops mv88e6320_ops = {
|
||||
|
@ -3253,6 +3261,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
|
|||
.vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
|
||||
.gpio_ops = &mv88e6352_gpio_ops,
|
||||
.avb_ops = &mv88e6352_avb_ops,
|
||||
.ptp_ops = &mv88e6352_ptp_ops,
|
||||
};
|
||||
|
||||
static const struct mv88e6xxx_ops mv88e6321_ops = {
|
||||
|
@ -3289,6 +3298,7 @@ static const struct mv88e6xxx_ops mv88e6321_ops = {
|
|||
.vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
|
||||
.gpio_ops = &mv88e6352_gpio_ops,
|
||||
.avb_ops = &mv88e6352_avb_ops,
|
||||
.ptp_ops = &mv88e6352_ptp_ops,
|
||||
};
|
||||
|
||||
static const struct mv88e6xxx_ops mv88e6341_ops = {
|
||||
|
@ -3329,6 +3339,7 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
|
|||
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
|
||||
.gpio_ops = &mv88e6352_gpio_ops,
|
||||
.avb_ops = &mv88e6390_avb_ops,
|
||||
.ptp_ops = &mv88e6352_ptp_ops,
|
||||
};
|
||||
|
||||
static const struct mv88e6xxx_ops mv88e6350_ops = {
|
||||
|
@ -3402,6 +3413,7 @@ static const struct mv88e6xxx_ops mv88e6351_ops = {
|
|||
.vtu_getnext = mv88e6352_g1_vtu_getnext,
|
||||
.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
|
||||
.avb_ops = &mv88e6352_avb_ops,
|
||||
.ptp_ops = &mv88e6352_ptp_ops,
|
||||
};
|
||||
|
||||
static const struct mv88e6xxx_ops mv88e6352_ops = {
|
||||
|
@ -3444,6 +3456,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
|
|||
.serdes_power = mv88e6352_serdes_power,
|
||||
.gpio_ops = &mv88e6352_gpio_ops,
|
||||
.avb_ops = &mv88e6352_avb_ops,
|
||||
.ptp_ops = &mv88e6352_ptp_ops,
|
||||
.serdes_get_sset_count = mv88e6352_serdes_get_sset_count,
|
||||
.serdes_get_strings = mv88e6352_serdes_get_strings,
|
||||
.serdes_get_stats = mv88e6352_serdes_get_stats,
|
||||
|
@ -3488,6 +3501,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
|
|||
.serdes_power = mv88e6390_serdes_power,
|
||||
.gpio_ops = &mv88e6352_gpio_ops,
|
||||
.avb_ops = &mv88e6390_avb_ops,
|
||||
.ptp_ops = &mv88e6352_ptp_ops,
|
||||
};
|
||||
|
||||
static const struct mv88e6xxx_ops mv88e6390x_ops = {
|
||||
|
@ -3529,6 +3543,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
|
|||
.serdes_power = mv88e6390_serdes_power,
|
||||
.gpio_ops = &mv88e6352_gpio_ops,
|
||||
.avb_ops = &mv88e6390_avb_ops,
|
||||
.ptp_ops = &mv88e6352_ptp_ops,
|
||||
};
|
||||
|
||||
static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
|
@ -3680,6 +3695,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
.tag_protocol = DSA_TAG_PROTO_EDSA,
|
||||
.ptp_support = true,
|
||||
.ops = &mv88e6161_ops,
|
||||
},
|
||||
|
||||
|
@ -3702,6 +3718,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
|||
.pvt = true,
|
||||
.multi_chip = true,
|
||||
.tag_protocol = DSA_TAG_PROTO_DSA,
|
||||
.ptp_support = true,
|
||||
.ops = &mv88e6165_ops,
|
||||
},
|
||||
|
||||
|
|
|
@ -155,6 +155,7 @@ struct mv88e6xxx_bus_ops;
|
|||
struct mv88e6xxx_irq_ops;
|
||||
struct mv88e6xxx_gpio_ops;
|
||||
struct mv88e6xxx_avb_ops;
|
||||
struct mv88e6xxx_ptp_ops;
|
||||
|
||||
struct mv88e6xxx_irq {
|
||||
u16 masked;
|
||||
|
@ -273,6 +274,7 @@ struct mv88e6xxx_chip {
|
|||
struct ptp_pin_desc pin_config[MV88E6XXX_MAX_GPIO];
|
||||
u16 trig_config;
|
||||
u16 evcap_config;
|
||||
u16 enable_count;
|
||||
|
||||
/* Per-port timestamping resources. */
|
||||
struct mv88e6xxx_port_hwtstamp port_hwtstamp[DSA_MAX_PORTS];
|
||||
|
@ -439,6 +441,9 @@ struct mv88e6xxx_ops {
|
|||
|
||||
/* Remote Management Unit operations */
|
||||
int (*rmu_disable)(struct mv88e6xxx_chip *chip);
|
||||
|
||||
/* Precision Time Protocol operations */
|
||||
const struct mv88e6xxx_ptp_ops *ptp_ops;
|
||||
};
|
||||
|
||||
struct mv88e6xxx_irq_ops {
|
||||
|
@ -486,6 +491,24 @@ struct mv88e6xxx_avb_ops {
|
|||
int (*tai_write)(struct mv88e6xxx_chip *chip, int addr, u16 data);
|
||||
};
|
||||
|
||||
struct mv88e6xxx_ptp_ops {
|
||||
u64 (*clock_read)(const struct cyclecounter *cc);
|
||||
int (*ptp_enable)(struct ptp_clock_info *ptp,
|
||||
struct ptp_clock_request *rq, int on);
|
||||
int (*ptp_verify)(struct ptp_clock_info *ptp, unsigned int pin,
|
||||
enum ptp_pin_function func, unsigned int chan);
|
||||
void (*event_work)(struct work_struct *ugly);
|
||||
int (*port_enable)(struct mv88e6xxx_chip *chip, int port);
|
||||
int (*port_disable)(struct mv88e6xxx_chip *chip, int port);
|
||||
int (*global_enable)(struct mv88e6xxx_chip *chip);
|
||||
int (*global_disable)(struct mv88e6xxx_chip *chip);
|
||||
int n_ext_ts;
|
||||
int arr0_sts_reg;
|
||||
int arr1_sts_reg;
|
||||
int dep_sts_reg;
|
||||
u32 rx_filters;
|
||||
};
|
||||
|
||||
#define STATS_TYPE_PORT BIT(0)
|
||||
#define STATS_TYPE_BANK0 BIT(1)
|
||||
#define STATS_TYPE_BANK1 BIT(2)
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
#define MV88E6390_G2_AVB_CMD_OP_WRITE 0x6000
|
||||
#define MV88E6352_G2_AVB_CMD_PORT_MASK 0x0f00
|
||||
#define MV88E6352_G2_AVB_CMD_PORT_TAIGLOBAL 0xe
|
||||
#define MV88E6165_G2_AVB_CMD_PORT_PTPGLOBAL 0xf
|
||||
#define MV88E6352_G2_AVB_CMD_PORT_PTPGLOBAL 0xf
|
||||
#define MV88E6390_G2_AVB_CMD_PORT_MASK 0x1f00
|
||||
#define MV88E6390_G2_AVB_CMD_PORT_TAIGLOBAL 0x1e
|
||||
|
@ -335,6 +336,7 @@ int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target,
|
|||
extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops;
|
||||
extern const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops;
|
||||
|
||||
extern const struct mv88e6xxx_avb_ops mv88e6165_avb_ops;
|
||||
extern const struct mv88e6xxx_avb_ops mv88e6352_avb_ops;
|
||||
extern const struct mv88e6xxx_avb_ops mv88e6390_avb_ops;
|
||||
|
||||
|
@ -484,6 +486,7 @@ static inline int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip)
|
|||
static const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops = {};
|
||||
static const struct mv88e6xxx_irq_ops mv88e6390_watchdog_ops = {};
|
||||
|
||||
static const struct mv88e6xxx_avb_ops mv88e6165_avb_ops = {};
|
||||
static const struct mv88e6xxx_avb_ops mv88e6352_avb_ops = {};
|
||||
static const struct mv88e6xxx_avb_ops mv88e6390_avb_ops = {};
|
||||
|
||||
|
|
|
@ -130,6 +130,31 @@ const struct mv88e6xxx_avb_ops mv88e6352_avb_ops = {
|
|||
.tai_write = mv88e6352_g2_avb_tai_write,
|
||||
};
|
||||
|
||||
static int mv88e6165_g2_avb_tai_read(struct mv88e6xxx_chip *chip, int addr,
|
||||
u16 *data, int len)
|
||||
{
|
||||
return mv88e6352_g2_avb_port_ptp_read(chip,
|
||||
MV88E6165_G2_AVB_CMD_PORT_PTPGLOBAL,
|
||||
addr, data, len);
|
||||
}
|
||||
|
||||
static int mv88e6165_g2_avb_tai_write(struct mv88e6xxx_chip *chip, int addr,
|
||||
u16 data)
|
||||
{
|
||||
return mv88e6352_g2_avb_port_ptp_write(chip,
|
||||
MV88E6165_G2_AVB_CMD_PORT_PTPGLOBAL,
|
||||
addr, data);
|
||||
}
|
||||
|
||||
const struct mv88e6xxx_avb_ops mv88e6165_avb_ops = {
|
||||
.port_ptp_read = mv88e6352_g2_avb_port_ptp_read,
|
||||
.port_ptp_write = mv88e6352_g2_avb_port_ptp_write,
|
||||
.ptp_read = mv88e6352_g2_avb_ptp_read,
|
||||
.ptp_write = mv88e6352_g2_avb_ptp_write,
|
||||
.tai_read = mv88e6165_g2_avb_tai_read,
|
||||
.tai_write = mv88e6165_g2_avb_tai_write,
|
||||
};
|
||||
|
||||
static int mv88e6390_g2_avb_port_ptp_read(struct mv88e6xxx_chip *chip,
|
||||
int port, int addr, u16 *data,
|
||||
int len)
|
||||
|
|
|
@ -51,17 +51,30 @@ static int mv88e6xxx_ptp_write(struct mv88e6xxx_chip *chip, int addr,
|
|||
return chip->info->ops->avb_ops->ptp_write(chip, addr, data);
|
||||
}
|
||||
|
||||
static int mv88e6xxx_ptp_read(struct mv88e6xxx_chip *chip, int addr,
|
||||
u16 *data)
|
||||
{
|
||||
if (!chip->info->ops->avb_ops->ptp_read)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return chip->info->ops->avb_ops->ptp_read(chip, addr, data, 1);
|
||||
}
|
||||
|
||||
/* TX_TSTAMP_TIMEOUT: This limits the time spent polling for a TX
|
||||
* timestamp. When working properly, hardware will produce a timestamp
|
||||
* within 1ms. Software may enounter delays due to MDIO contention, so
|
||||
* the timeout is set accordingly.
|
||||
*/
|
||||
#define TX_TSTAMP_TIMEOUT msecs_to_jiffies(20)
|
||||
#define TX_TSTAMP_TIMEOUT msecs_to_jiffies(40)
|
||||
|
||||
int mv88e6xxx_get_ts_info(struct dsa_switch *ds, int port,
|
||||
struct ethtool_ts_info *info)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = ds->priv;
|
||||
const struct mv88e6xxx_ptp_ops *ptp_ops;
|
||||
struct mv88e6xxx_chip *chip;
|
||||
|
||||
chip = ds->priv;
|
||||
ptp_ops = chip->info->ops->ptp_ops;
|
||||
|
||||
if (!chip->info->ptp_support)
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -74,17 +87,7 @@ int mv88e6xxx_get_ts_info(struct dsa_switch *ds, int port,
|
|||
info->tx_types =
|
||||
(1 << HWTSTAMP_TX_OFF) |
|
||||
(1 << HWTSTAMP_TX_ON);
|
||||
info->rx_filters =
|
||||
(1 << HWTSTAMP_FILTER_NONE) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ);
|
||||
info->rx_filters = ptp_ops->rx_filters;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -92,10 +95,9 @@ int mv88e6xxx_get_ts_info(struct dsa_switch *ds, int port,
|
|||
static int mv88e6xxx_set_hwtstamp_config(struct mv88e6xxx_chip *chip, int port,
|
||||
struct hwtstamp_config *config)
|
||||
{
|
||||
const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
|
||||
struct mv88e6xxx_port_hwtstamp *ps = &chip->port_hwtstamp[port];
|
||||
bool tstamp_enable = false;
|
||||
u16 port_config0;
|
||||
int err;
|
||||
|
||||
/* Prevent the TX/RX paths from trying to interact with the
|
||||
* timestamp hardware while we reconfigure it.
|
||||
|
@ -120,6 +122,14 @@ static int mv88e6xxx_set_hwtstamp_config(struct mv88e6xxx_chip *chip, int port,
|
|||
/* The switch supports timestamping both L2 and L4; one cannot be
|
||||
* disabled independently of the other.
|
||||
*/
|
||||
|
||||
if (!(BIT(config->rx_filter) & ptp_ops->rx_filters)) {
|
||||
config->rx_filter = HWTSTAMP_FILTER_NONE;
|
||||
dev_dbg(chip->dev, "Unsupported rx_filter %d\n",
|
||||
config->rx_filter);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
switch (config->rx_filter) {
|
||||
case HWTSTAMP_FILTER_NONE:
|
||||
tstamp_enable = false;
|
||||
|
@ -141,24 +151,22 @@ static int mv88e6xxx_set_hwtstamp_config(struct mv88e6xxx_chip *chip, int port,
|
|||
return -ERANGE;
|
||||
}
|
||||
|
||||
if (tstamp_enable) {
|
||||
/* Disable transportSpecific value matching, so that packets
|
||||
* with either 1588 (0) and 802.1AS (1) will be timestamped.
|
||||
*/
|
||||
port_config0 = MV88E6XXX_PORT_PTP_CFG0_DISABLE_TSPEC_MATCH;
|
||||
} else {
|
||||
/* Disable PTP. This disables both RX and TX timestamping. */
|
||||
port_config0 = MV88E6XXX_PORT_PTP_CFG0_DISABLE_PTP;
|
||||
}
|
||||
|
||||
mutex_lock(&chip->reg_lock);
|
||||
err = mv88e6xxx_port_ptp_write(chip, port, MV88E6XXX_PORT_PTP_CFG0,
|
||||
port_config0);
|
||||
if (tstamp_enable) {
|
||||
chip->enable_count += 1;
|
||||
if (chip->enable_count == 1 && ptp_ops->global_enable)
|
||||
ptp_ops->global_enable(chip);
|
||||
if (ptp_ops->port_enable)
|
||||
ptp_ops->port_enable(chip, port);
|
||||
} else {
|
||||
if (ptp_ops->port_disable)
|
||||
ptp_ops->port_disable(chip, port);
|
||||
chip->enable_count -= 1;
|
||||
if (chip->enable_count == 0 && ptp_ops->global_disable)
|
||||
ptp_ops->global_disable(chip);
|
||||
}
|
||||
mutex_unlock(&chip->reg_lock);
|
||||
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* Once hardware has been configured, enable timestamp checks
|
||||
* in the RX/TX paths.
|
||||
*/
|
||||
|
@ -338,17 +346,18 @@ static void mv88e6xxx_get_rxts(struct mv88e6xxx_chip *chip,
|
|||
static void mv88e6xxx_rxtstamp_work(struct mv88e6xxx_chip *chip,
|
||||
struct mv88e6xxx_port_hwtstamp *ps)
|
||||
{
|
||||
const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = skb_dequeue(&ps->rx_queue);
|
||||
|
||||
if (skb)
|
||||
mv88e6xxx_get_rxts(chip, ps, skb, MV88E6XXX_PORT_PTP_ARR0_STS,
|
||||
mv88e6xxx_get_rxts(chip, ps, skb, ptp_ops->arr0_sts_reg,
|
||||
&ps->rx_queue);
|
||||
|
||||
skb = skb_dequeue(&ps->rx_queue2);
|
||||
if (skb)
|
||||
mv88e6xxx_get_rxts(chip, ps, skb, MV88E6XXX_PORT_PTP_ARR1_STS,
|
||||
mv88e6xxx_get_rxts(chip, ps, skb, ptp_ops->arr1_sts_reg,
|
||||
&ps->rx_queue2);
|
||||
}
|
||||
|
||||
|
@ -389,6 +398,7 @@ bool mv88e6xxx_port_rxtstamp(struct dsa_switch *ds, int port,
|
|||
static int mv88e6xxx_txtstamp_work(struct mv88e6xxx_chip *chip,
|
||||
struct mv88e6xxx_port_hwtstamp *ps)
|
||||
{
|
||||
const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
|
||||
struct skb_shared_hwtstamps shhwtstamps;
|
||||
u16 departure_block[4], status;
|
||||
struct sk_buff *tmp_skb;
|
||||
|
@ -401,7 +411,7 @@ static int mv88e6xxx_txtstamp_work(struct mv88e6xxx_chip *chip,
|
|||
|
||||
mutex_lock(&chip->reg_lock);
|
||||
err = mv88e6xxx_port_ptp_read(chip, ps->port_id,
|
||||
MV88E6XXX_PORT_PTP_DEP_STS,
|
||||
ptp_ops->dep_sts_reg,
|
||||
departure_block,
|
||||
ARRAY_SIZE(departure_block));
|
||||
mutex_unlock(&chip->reg_lock);
|
||||
|
@ -425,8 +435,7 @@ static int mv88e6xxx_txtstamp_work(struct mv88e6xxx_chip *chip,
|
|||
|
||||
/* We have the timestamp; go ahead and clear valid now */
|
||||
mutex_lock(&chip->reg_lock);
|
||||
mv88e6xxx_port_ptp_write(chip, ps->port_id,
|
||||
MV88E6XXX_PORT_PTP_DEP_STS, 0);
|
||||
mv88e6xxx_port_ptp_write(chip, ps->port_id, ptp_ops->dep_sts_reg, 0);
|
||||
mutex_unlock(&chip->reg_lock);
|
||||
|
||||
status = departure_block[0] & MV88E6XXX_PTP_TS_STATUS_MASK;
|
||||
|
@ -522,8 +531,48 @@ bool mv88e6xxx_port_txtstamp(struct dsa_switch *ds, int port,
|
|||
return true;
|
||||
}
|
||||
|
||||
int mv88e6165_global_disable(struct mv88e6xxx_chip *chip)
|
||||
{
|
||||
u16 val;
|
||||
int err;
|
||||
|
||||
err = mv88e6xxx_ptp_read(chip, MV88E6165_PTP_CFG, &val);
|
||||
if (err)
|
||||
return err;
|
||||
val |= MV88E6165_PTP_CFG_DISABLE_PTP;
|
||||
|
||||
return mv88e6xxx_ptp_write(chip, MV88E6165_PTP_CFG, val);
|
||||
}
|
||||
|
||||
int mv88e6165_global_enable(struct mv88e6xxx_chip *chip)
|
||||
{
|
||||
u16 val;
|
||||
int err;
|
||||
|
||||
err = mv88e6xxx_ptp_read(chip, MV88E6165_PTP_CFG, &val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
val &= ~(MV88E6165_PTP_CFG_DISABLE_PTP | MV88E6165_PTP_CFG_TSPEC_MASK);
|
||||
|
||||
return mv88e6xxx_ptp_write(chip, MV88E6165_PTP_CFG, val);
|
||||
}
|
||||
|
||||
int mv88e6352_hwtstamp_port_disable(struct mv88e6xxx_chip *chip, int port)
|
||||
{
|
||||
return mv88e6xxx_port_ptp_write(chip, port, MV88E6XXX_PORT_PTP_CFG0,
|
||||
MV88E6XXX_PORT_PTP_CFG0_DISABLE_PTP);
|
||||
}
|
||||
|
||||
int mv88e6352_hwtstamp_port_enable(struct mv88e6xxx_chip *chip, int port)
|
||||
{
|
||||
return mv88e6xxx_port_ptp_write(chip, port, MV88E6XXX_PORT_PTP_CFG0,
|
||||
MV88E6XXX_PORT_PTP_CFG0_DISABLE_TSPEC_MATCH);
|
||||
}
|
||||
|
||||
static int mv88e6xxx_hwtstamp_port_setup(struct mv88e6xxx_chip *chip, int port)
|
||||
{
|
||||
const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
|
||||
struct mv88e6xxx_port_hwtstamp *ps = &chip->port_hwtstamp[port];
|
||||
|
||||
ps->port_id = port;
|
||||
|
@ -531,12 +580,15 @@ static int mv88e6xxx_hwtstamp_port_setup(struct mv88e6xxx_chip *chip, int port)
|
|||
skb_queue_head_init(&ps->rx_queue);
|
||||
skb_queue_head_init(&ps->rx_queue2);
|
||||
|
||||
return mv88e6xxx_port_ptp_write(chip, port, MV88E6XXX_PORT_PTP_CFG0,
|
||||
MV88E6XXX_PORT_PTP_CFG0_DISABLE_PTP);
|
||||
if (ptp_ops->port_disable)
|
||||
return ptp_ops->port_disable(chip, port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mv88e6xxx_hwtstamp_setup(struct mv88e6xxx_chip *chip)
|
||||
{
|
||||
const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
|
@ -547,6 +599,18 @@ int mv88e6xxx_hwtstamp_setup(struct mv88e6xxx_chip *chip)
|
|||
return err;
|
||||
}
|
||||
|
||||
/* Disable PTP globally */
|
||||
if (ptp_ops->global_disable) {
|
||||
err = ptp_ops->global_disable(chip);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Set the ethertype of L2 PTP messages */
|
||||
err = mv88e6xxx_ptp_write(chip, MV88E6XXX_PTP_GC_ETYPE, ETH_P_1588);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* MV88E6XXX_PTP_MSG_TYPE is a mask of PTP message types to
|
||||
* timestamp. This affects all ports that have timestamping enabled,
|
||||
* but the timestamp config is per-port; thus we configure all events
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include "chip.h"
|
||||
|
||||
/* Global PTP registers */
|
||||
/* Global 6352 PTP registers */
|
||||
/* Offset 0x00: PTP EtherType */
|
||||
#define MV88E6XXX_PTP_ETHERTYPE 0x00
|
||||
|
||||
|
@ -34,6 +34,12 @@
|
|||
/* Offset 0x02: Timestamp Arrival Capture Pointers */
|
||||
#define MV88E6XXX_PTP_TS_ARRIVAL_PTR 0x02
|
||||
|
||||
/* Offset 0x05: PTP Global Configuration */
|
||||
#define MV88E6165_PTP_CFG 0x05
|
||||
#define MV88E6165_PTP_CFG_TSPEC_MASK 0xf000
|
||||
#define MV88E6165_PTP_CFG_DISABLE_TS_OVERWRITE BIT(1)
|
||||
#define MV88E6165_PTP_CFG_DISABLE_PTP BIT(0)
|
||||
|
||||
/* Offset 0x07: PTP Global Configuration */
|
||||
#define MV88E6341_PTP_CFG 0x07
|
||||
#define MV88E6341_PTP_CFG_UPDATE 0x8000
|
||||
|
@ -46,7 +52,7 @@
|
|||
/* Offset 0x08: PTP Interrupt Status */
|
||||
#define MV88E6XXX_PTP_IRQ_STATUS 0x08
|
||||
|
||||
/* Per-Port PTP Registers */
|
||||
/* Per-Port 6352 PTP Registers */
|
||||
/* Offset 0x00: PTP Configuration 0 */
|
||||
#define MV88E6XXX_PORT_PTP_CFG0 0x00
|
||||
#define MV88E6XXX_PORT_PTP_CFG0_TSPEC_SHIFT 12
|
||||
|
@ -123,6 +129,10 @@ int mv88e6xxx_get_ts_info(struct dsa_switch *ds, int port,
|
|||
|
||||
int mv88e6xxx_hwtstamp_setup(struct mv88e6xxx_chip *chip);
|
||||
void mv88e6xxx_hwtstamp_free(struct mv88e6xxx_chip *chip);
|
||||
int mv88e6352_hwtstamp_port_enable(struct mv88e6xxx_chip *chip, int port);
|
||||
int mv88e6352_hwtstamp_port_disable(struct mv88e6xxx_chip *chip, int port);
|
||||
int mv88e6165_global_enable(struct mv88e6xxx_chip *chip);
|
||||
int mv88e6165_global_disable(struct mv88e6xxx_chip *chip);
|
||||
|
||||
#else /* !CONFIG_NET_DSA_MV88E6XXX_PTP */
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "chip.h"
|
||||
#include "global2.h"
|
||||
#include "hwtstamp.h"
|
||||
#include "ptp.h"
|
||||
|
||||
/* Raw timestamps are in units of 8-ns clock periods. */
|
||||
|
@ -50,7 +51,7 @@ static int mv88e6xxx_tai_write(struct mv88e6xxx_chip *chip, int addr, u16 data)
|
|||
}
|
||||
|
||||
/* TODO: places where this are called should be using pinctrl */
|
||||
static int mv88e6xxx_set_gpio_func(struct mv88e6xxx_chip *chip, int pin,
|
||||
static int mv88e6352_set_gpio_func(struct mv88e6xxx_chip *chip, int pin,
|
||||
int func, int input)
|
||||
{
|
||||
int err;
|
||||
|
@ -65,7 +66,7 @@ static int mv88e6xxx_set_gpio_func(struct mv88e6xxx_chip *chip, int pin,
|
|||
return chip->info->ops->gpio_ops->set_pctl(chip, pin, func);
|
||||
}
|
||||
|
||||
static u64 mv88e6xxx_ptp_clock_read(const struct cyclecounter *cc)
|
||||
static u64 mv88e6352_ptp_clock_read(const struct cyclecounter *cc)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = cc_to_chip(cc);
|
||||
u16 phc_time[2];
|
||||
|
@ -79,13 +80,27 @@ static u64 mv88e6xxx_ptp_clock_read(const struct cyclecounter *cc)
|
|||
return ((u32)phc_time[1] << 16) | phc_time[0];
|
||||
}
|
||||
|
||||
/* mv88e6xxx_config_eventcap - configure TAI event capture
|
||||
static u64 mv88e6165_ptp_clock_read(const struct cyclecounter *cc)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = cc_to_chip(cc);
|
||||
u16 phc_time[2];
|
||||
int err;
|
||||
|
||||
err = mv88e6xxx_tai_read(chip, MV88E6XXX_PTP_GC_TIME_LO, phc_time,
|
||||
ARRAY_SIZE(phc_time));
|
||||
if (err)
|
||||
return 0;
|
||||
else
|
||||
return ((u32)phc_time[1] << 16) | phc_time[0];
|
||||
}
|
||||
|
||||
/* mv88e6352_config_eventcap - configure TAI event capture
|
||||
* @event: PTP_CLOCK_PPS (internal) or PTP_CLOCK_EXTTS (external)
|
||||
* @rising: zero for falling-edge trigger, else rising-edge trigger
|
||||
*
|
||||
* This will also reset the capture sequence counter.
|
||||
*/
|
||||
static int mv88e6xxx_config_eventcap(struct mv88e6xxx_chip *chip, int event,
|
||||
static int mv88e6352_config_eventcap(struct mv88e6xxx_chip *chip, int event,
|
||||
int rising)
|
||||
{
|
||||
u16 global_config;
|
||||
|
@ -118,7 +133,7 @@ static int mv88e6xxx_config_eventcap(struct mv88e6xxx_chip *chip, int event,
|
|||
return err;
|
||||
}
|
||||
|
||||
static void mv88e6xxx_tai_event_work(struct work_struct *ugly)
|
||||
static void mv88e6352_tai_event_work(struct work_struct *ugly)
|
||||
{
|
||||
struct delayed_work *dw = to_delayed_work(ugly);
|
||||
struct mv88e6xxx_chip *chip = dw_tai_event_to_chip(dw);
|
||||
|
@ -232,7 +247,7 @@ static int mv88e6xxx_ptp_settime(struct ptp_clock_info *ptp,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mv88e6xxx_ptp_enable_extts(struct mv88e6xxx_chip *chip,
|
||||
static int mv88e6352_ptp_enable_extts(struct mv88e6xxx_chip *chip,
|
||||
struct ptp_clock_request *rq, int on)
|
||||
{
|
||||
int rising = (rq->extts.flags & PTP_RISING_EDGE);
|
||||
|
@ -250,18 +265,18 @@ static int mv88e6xxx_ptp_enable_extts(struct mv88e6xxx_chip *chip,
|
|||
if (on) {
|
||||
func = MV88E6352_G2_SCRATCH_GPIO_PCTL_EVREQ;
|
||||
|
||||
err = mv88e6xxx_set_gpio_func(chip, pin, func, true);
|
||||
err = mv88e6352_set_gpio_func(chip, pin, func, true);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
schedule_delayed_work(&chip->tai_event_work,
|
||||
TAI_EVENT_WORK_INTERVAL);
|
||||
|
||||
err = mv88e6xxx_config_eventcap(chip, PTP_CLOCK_EXTTS, rising);
|
||||
err = mv88e6352_config_eventcap(chip, PTP_CLOCK_EXTTS, rising);
|
||||
} else {
|
||||
func = MV88E6352_G2_SCRATCH_GPIO_PCTL_GPIO;
|
||||
|
||||
err = mv88e6xxx_set_gpio_func(chip, pin, func, true);
|
||||
err = mv88e6352_set_gpio_func(chip, pin, func, true);
|
||||
|
||||
cancel_delayed_work_sync(&chip->tai_event_work);
|
||||
}
|
||||
|
@ -272,20 +287,20 @@ static int mv88e6xxx_ptp_enable_extts(struct mv88e6xxx_chip *chip,
|
|||
return err;
|
||||
}
|
||||
|
||||
static int mv88e6xxx_ptp_enable(struct ptp_clock_info *ptp,
|
||||
static int mv88e6352_ptp_enable(struct ptp_clock_info *ptp,
|
||||
struct ptp_clock_request *rq, int on)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
|
||||
|
||||
switch (rq->type) {
|
||||
case PTP_CLK_REQ_EXTTS:
|
||||
return mv88e6xxx_ptp_enable_extts(chip, rq, on);
|
||||
return mv88e6352_ptp_enable_extts(chip, rq, on);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
static int mv88e6xxx_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin,
|
||||
static int mv88e6352_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin,
|
||||
enum ptp_pin_function func, unsigned int chan)
|
||||
{
|
||||
switch (func) {
|
||||
|
@ -299,6 +314,55 @@ static int mv88e6xxx_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin,
|
|||
return 0;
|
||||
}
|
||||
|
||||
const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {
|
||||
.clock_read = mv88e6352_ptp_clock_read,
|
||||
.ptp_enable = mv88e6352_ptp_enable,
|
||||
.ptp_verify = mv88e6352_ptp_verify,
|
||||
.event_work = mv88e6352_tai_event_work,
|
||||
.port_enable = mv88e6352_hwtstamp_port_enable,
|
||||
.port_disable = mv88e6352_hwtstamp_port_disable,
|
||||
.n_ext_ts = 1,
|
||||
.arr0_sts_reg = MV88E6XXX_PORT_PTP_ARR0_STS,
|
||||
.arr1_sts_reg = MV88E6XXX_PORT_PTP_ARR1_STS,
|
||||
.dep_sts_reg = MV88E6XXX_PORT_PTP_DEP_STS,
|
||||
.rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
|
||||
};
|
||||
|
||||
const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops = {
|
||||
.clock_read = mv88e6165_ptp_clock_read,
|
||||
.global_enable = mv88e6165_global_enable,
|
||||
.global_disable = mv88e6165_global_disable,
|
||||
.arr0_sts_reg = MV88E6165_PORT_PTP_ARR0_STS,
|
||||
.arr1_sts_reg = MV88E6165_PORT_PTP_ARR1_STS,
|
||||
.dep_sts_reg = MV88E6165_PORT_PTP_DEP_STS,
|
||||
.rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
|
||||
};
|
||||
|
||||
static u64 mv88e6xxx_ptp_clock_read(const struct cyclecounter *cc)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = cc_to_chip(cc);
|
||||
|
||||
if (chip->info->ops->ptp_ops->clock_read)
|
||||
return chip->info->ops->ptp_ops->clock_read(cc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* With a 125MHz input clock, the 32-bit timestamp counter overflows in ~34.3
|
||||
* seconds; this task forces periodic reads so that we don't miss any.
|
||||
*/
|
||||
|
@ -317,6 +381,7 @@ static void mv88e6xxx_ptp_overflow_check(struct work_struct *work)
|
|||
|
||||
int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
|
||||
{
|
||||
const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
|
||||
int i;
|
||||
|
||||
/* Set up the cycle counter */
|
||||
|
@ -330,14 +395,15 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
|
|||
ktime_to_ns(ktime_get_real()));
|
||||
|
||||
INIT_DELAYED_WORK(&chip->overflow_work, mv88e6xxx_ptp_overflow_check);
|
||||
INIT_DELAYED_WORK(&chip->tai_event_work, mv88e6xxx_tai_event_work);
|
||||
if (ptp_ops->event_work)
|
||||
INIT_DELAYED_WORK(&chip->tai_event_work, ptp_ops->event_work);
|
||||
|
||||
chip->ptp_clock_info.owner = THIS_MODULE;
|
||||
snprintf(chip->ptp_clock_info.name, sizeof(chip->ptp_clock_info.name),
|
||||
dev_name(chip->dev));
|
||||
chip->ptp_clock_info.max_adj = 1000000;
|
||||
|
||||
chip->ptp_clock_info.n_ext_ts = 1;
|
||||
chip->ptp_clock_info.n_ext_ts = ptp_ops->n_ext_ts;
|
||||
chip->ptp_clock_info.n_per_out = 0;
|
||||
chip->ptp_clock_info.n_pins = mv88e6xxx_num_gpio(chip);
|
||||
chip->ptp_clock_info.pps = 0;
|
||||
|
@ -355,8 +421,8 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
|
|||
chip->ptp_clock_info.adjtime = mv88e6xxx_ptp_adjtime;
|
||||
chip->ptp_clock_info.gettime64 = mv88e6xxx_ptp_gettime;
|
||||
chip->ptp_clock_info.settime64 = mv88e6xxx_ptp_settime;
|
||||
chip->ptp_clock_info.enable = mv88e6xxx_ptp_enable;
|
||||
chip->ptp_clock_info.verify = mv88e6xxx_ptp_verify;
|
||||
chip->ptp_clock_info.enable = ptp_ops->ptp_enable;
|
||||
chip->ptp_clock_info.verify = ptp_ops->ptp_verify;
|
||||
chip->ptp_clock_info.do_aux_work = mv88e6xxx_hwtstamp_work;
|
||||
|
||||
chip->ptp_clock = ptp_clock_register(&chip->ptp_clock_info, chip->dev);
|
||||
|
@ -373,7 +439,8 @@ void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip)
|
|||
{
|
||||
if (chip->ptp_clock) {
|
||||
cancel_delayed_work_sync(&chip->overflow_work);
|
||||
cancel_delayed_work_sync(&chip->tai_event_work);
|
||||
if (chip->info->ops->ptp_ops->event_work)
|
||||
cancel_delayed_work_sync(&chip->tai_event_work);
|
||||
|
||||
ptp_clock_unregister(chip->ptp_clock);
|
||||
chip->ptp_clock = NULL;
|
||||
|
|
|
@ -78,6 +78,71 @@
|
|||
/* Offset 0x12: Lock Status */
|
||||
#define MV88E6XXX_TAI_LOCK_STATUS 0x12
|
||||
|
||||
/* Offset 0x00: Ether Type */
|
||||
#define MV88E6XXX_PTP_GC_ETYPE 0x00
|
||||
|
||||
/* 6165 Global Control Registers */
|
||||
/* Offset 0x00: Ether Type */
|
||||
#define MV88E6XXX_PTP_GC_ETYPE 0x00
|
||||
|
||||
/* Offset 0x01: Message ID */
|
||||
#define MV88E6XXX_PTP_GC_MESSAGE_ID 0x01
|
||||
|
||||
/* Offset 0x02: Time Stamp Arrive Time */
|
||||
#define MV88E6XXX_PTP_GC_TS_ARR_PTR 0x02
|
||||
|
||||
/* Offset 0x03: Port Arrival Interrupt Enable */
|
||||
#define MV88E6XXX_PTP_GC_PORT_ARR_INT_EN 0x03
|
||||
|
||||
/* Offset 0x04: Port Departure Interrupt Enable */
|
||||
#define MV88E6XXX_PTP_GC_PORT_DEP_INT_EN 0x04
|
||||
|
||||
/* Offset 0x05: Configuration */
|
||||
#define MV88E6XXX_PTP_GC_CONFIG 0x05
|
||||
#define MV88E6XXX_PTP_GC_CONFIG_DIS_OVERWRITE BIT(1)
|
||||
#define MV88E6XXX_PTP_GC_CONFIG_DIS_TS BIT(0)
|
||||
|
||||
/* Offset 0x8: Interrupt Status */
|
||||
#define MV88E6XXX_PTP_GC_INT_STATUS 0x08
|
||||
|
||||
/* Offset 0x9/0xa: Global Time */
|
||||
#define MV88E6XXX_PTP_GC_TIME_LO 0x09
|
||||
#define MV88E6XXX_PTP_GC_TIME_HI 0x0A
|
||||
|
||||
/* 6165 Per Port Registers */
|
||||
/* Offset 0: Arrival Time 0 Status */
|
||||
#define MV88E6165_PORT_PTP_ARR0_STS 0x00
|
||||
|
||||
/* Offset 0x01/0x02: PTP Arrival 0 Time */
|
||||
#define MV88E6165_PORT_PTP_ARR0_TIME_LO 0x01
|
||||
#define MV88E6165_PORT_PTP_ARR0_TIME_HI 0x02
|
||||
|
||||
/* Offset 0x03: PTP Arrival 0 Sequence ID */
|
||||
#define MV88E6165_PORT_PTP_ARR0_SEQID 0x03
|
||||
|
||||
/* Offset 0x04: PTP Arrival 1 Status */
|
||||
#define MV88E6165_PORT_PTP_ARR1_STS 0x04
|
||||
|
||||
/* Offset 0x05/0x6E: PTP Arrival 1 Time */
|
||||
#define MV88E6165_PORT_PTP_ARR1_TIME_LO 0x05
|
||||
#define MV88E6165_PORT_PTP_ARR1_TIME_HI 0x06
|
||||
|
||||
/* Offset 0x07: PTP Arrival 1 Sequence ID */
|
||||
#define MV88E6165_PORT_PTP_ARR1_SEQID 0x07
|
||||
|
||||
/* Offset 0x08: PTP Departure Status */
|
||||
#define MV88E6165_PORT_PTP_DEP_STS 0x08
|
||||
|
||||
/* Offset 0x09/0x0a: PTP Deperture Time */
|
||||
#define MV88E6165_PORT_PTP_DEP_TIME_LO 0x09
|
||||
#define MV88E6165_PORT_PTP_DEP_TIME_HI 0x0a
|
||||
|
||||
/* Offset 0x0b: PTP Departure Sequence ID */
|
||||
#define MV88E6165_PORT_PTP_DEP_SEQID 0x0b
|
||||
|
||||
/* Offset 0x0d: Port Status */
|
||||
#define MV88E6164_PORT_STATUS 0x0d
|
||||
|
||||
#ifdef CONFIG_NET_DSA_MV88E6XXX_PTP
|
||||
|
||||
long mv88e6xxx_hwtstamp_work(struct ptp_clock_info *ptp);
|
||||
|
@ -87,6 +152,9 @@ void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip);
|
|||
#define ptp_to_chip(ptp) container_of(ptp, struct mv88e6xxx_chip, \
|
||||
ptp_clock_info)
|
||||
|
||||
extern const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops;
|
||||
extern const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops;
|
||||
|
||||
#else /* !CONFIG_NET_DSA_MV88E6XXX_PTP */
|
||||
|
||||
static inline long mv88e6xxx_hwtstamp_work(struct ptp_clock_info *ptp)
|
||||
|
@ -103,6 +171,9 @@ static inline void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip)
|
|||
{
|
||||
}
|
||||
|
||||
static const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {};
|
||||
static const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops = {};
|
||||
|
||||
#endif /* CONFIG_NET_DSA_MV88E6XXX_PTP */
|
||||
|
||||
#endif /* _MV88E6XXX_PTP_H */
|
||||
|
|
Loading…
Reference in New Issue