forked from Minki/linux
net: dsa: mv88e6xxx: add PTP support for MV88E6250 family
This adds PTP support for the MV88E6250 family. Signed-off-by: Hubert Feurstein <h.feurstein@gmail.com> Acked-by: Richard Cochran <richardcochran@gmail.com> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
8858ccc837
commit
7150961487
@ -3538,6 +3538,8 @@ static const struct mv88e6xxx_ops mv88e6250_ops = {
|
||||
.reset = mv88e6250_g1_reset,
|
||||
.vtu_getnext = mv88e6250_g1_vtu_getnext,
|
||||
.vtu_loadpurge = mv88e6250_g1_vtu_loadpurge,
|
||||
.avb_ops = &mv88e6352_avb_ops,
|
||||
.ptp_ops = &mv88e6250_ptp_ops,
|
||||
.phylink_validate = mv88e6065_phylink_validate,
|
||||
};
|
||||
|
||||
@ -4334,6 +4336,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.atu_move_port_mask = 0xf,
|
||||
.dual_chip = true,
|
||||
.tag_protocol = DSA_TAG_PROTO_DSA,
|
||||
.ptp_support = true,
|
||||
.ops = &mv88e6250_ops,
|
||||
},
|
||||
|
||||
@ -4379,6 +4382,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
|
||||
.atu_move_port_mask = 0xf,
|
||||
.dual_chip = true,
|
||||
.tag_protocol = DSA_TAG_PROTO_DSA,
|
||||
.ptp_support = true,
|
||||
.ops = &mv88e6250_ops,
|
||||
},
|
||||
|
||||
|
@ -539,6 +539,10 @@ struct mv88e6xxx_ptp_ops {
|
||||
int arr1_sts_reg;
|
||||
int dep_sts_reg;
|
||||
u32 rx_filters;
|
||||
u32 cc_shift;
|
||||
u32 cc_mult;
|
||||
u32 cc_mult_num;
|
||||
u32 cc_mult_dem;
|
||||
};
|
||||
|
||||
#define STATS_TYPE_PORT BIT(0)
|
||||
|
@ -15,11 +15,31 @@
|
||||
#include "hwtstamp.h"
|
||||
#include "ptp.h"
|
||||
|
||||
/* Raw timestamps are in units of 8-ns clock periods. */
|
||||
#define CC_SHIFT 28
|
||||
#define CC_MULT (8 << CC_SHIFT)
|
||||
#define CC_MULT_NUM (1 << 9)
|
||||
#define CC_MULT_DEM 15625ULL
|
||||
#define MV88E6XXX_MAX_ADJ_PPB 1000000
|
||||
|
||||
/* Family MV88E6250:
|
||||
* Raw timestamps are in units of 10-ns clock periods.
|
||||
*
|
||||
* clkadj = scaled_ppm * 10*2^28 / (10^6 * 2^16)
|
||||
* simplifies to
|
||||
* clkadj = scaled_ppm * 2^7 / 5^5
|
||||
*/
|
||||
#define MV88E6250_CC_SHIFT 28
|
||||
#define MV88E6250_CC_MULT (10 << MV88E6250_CC_SHIFT)
|
||||
#define MV88E6250_CC_MULT_NUM (1 << 7)
|
||||
#define MV88E6250_CC_MULT_DEM 3125ULL
|
||||
|
||||
/* Other families:
|
||||
* Raw timestamps are in units of 8-ns clock periods.
|
||||
*
|
||||
* clkadj = scaled_ppm * 8*2^28 / (10^6 * 2^16)
|
||||
* simplifies to
|
||||
* clkadj = scaled_ppm * 2^9 / 5^6
|
||||
*/
|
||||
#define MV88E6XXX_CC_SHIFT 28
|
||||
#define MV88E6XXX_CC_MULT (8 << MV88E6XXX_CC_SHIFT)
|
||||
#define MV88E6XXX_CC_MULT_NUM (1 << 9)
|
||||
#define MV88E6XXX_CC_MULT_DEM 15625ULL
|
||||
|
||||
#define TAI_EVENT_WORK_INTERVAL msecs_to_jiffies(100)
|
||||
|
||||
@ -179,6 +199,7 @@ out:
|
||||
static int mv88e6xxx_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
|
||||
{
|
||||
struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
|
||||
const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
|
||||
int neg_adj = 0;
|
||||
u32 diff, mult;
|
||||
u64 adj;
|
||||
@ -187,10 +208,11 @@ static int mv88e6xxx_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
|
||||
neg_adj = 1;
|
||||
scaled_ppm = -scaled_ppm;
|
||||
}
|
||||
mult = CC_MULT;
|
||||
adj = CC_MULT_NUM;
|
||||
|
||||
mult = ptp_ops->cc_mult;
|
||||
adj = ptp_ops->cc_mult_num;
|
||||
adj *= scaled_ppm;
|
||||
diff = div_u64(adj, CC_MULT_DEM);
|
||||
diff = div_u64(adj, ptp_ops->cc_mult_dem);
|
||||
|
||||
mv88e6xxx_reg_lock(chip);
|
||||
|
||||
@ -324,6 +346,37 @@ const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops = {
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
|
||||
.cc_shift = MV88E6XXX_CC_SHIFT,
|
||||
.cc_mult = MV88E6XXX_CC_MULT,
|
||||
.cc_mult_num = MV88E6XXX_CC_MULT_NUM,
|
||||
.cc_mult_dem = MV88E6XXX_CC_MULT_DEM,
|
||||
};
|
||||
|
||||
const struct mv88e6xxx_ptp_ops mv88e6250_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),
|
||||
.cc_shift = MV88E6250_CC_SHIFT,
|
||||
.cc_mult = MV88E6250_CC_MULT,
|
||||
.cc_mult_num = MV88E6250_CC_MULT_NUM,
|
||||
.cc_mult_dem = MV88E6250_CC_MULT_DEM,
|
||||
};
|
||||
|
||||
const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {
|
||||
@ -347,6 +400,10 @@ const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
|
||||
(1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
|
||||
.cc_shift = MV88E6XXX_CC_SHIFT,
|
||||
.cc_mult = MV88E6XXX_CC_MULT,
|
||||
.cc_mult_num = MV88E6XXX_CC_MULT_NUM,
|
||||
.cc_mult_dem = MV88E6XXX_CC_MULT_DEM,
|
||||
};
|
||||
|
||||
static u64 mv88e6xxx_ptp_clock_read(const struct cyclecounter *cc)
|
||||
@ -384,8 +441,8 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
|
||||
memset(&chip->tstamp_cc, 0, sizeof(chip->tstamp_cc));
|
||||
chip->tstamp_cc.read = mv88e6xxx_ptp_clock_read;
|
||||
chip->tstamp_cc.mask = CYCLECOUNTER_MASK(32);
|
||||
chip->tstamp_cc.mult = CC_MULT;
|
||||
chip->tstamp_cc.shift = CC_SHIFT;
|
||||
chip->tstamp_cc.mult = ptp_ops->cc_mult;
|
||||
chip->tstamp_cc.shift = ptp_ops->cc_shift;
|
||||
|
||||
timecounter_init(&chip->tstamp_tc, &chip->tstamp_cc,
|
||||
ktime_to_ns(ktime_get_real()));
|
||||
@ -397,7 +454,6 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
|
||||
chip->ptp_clock_info.owner = THIS_MODULE;
|
||||
snprintf(chip->ptp_clock_info.name, sizeof(chip->ptp_clock_info.name),
|
||||
"%s", dev_name(chip->dev));
|
||||
chip->ptp_clock_info.max_adj = 1000000;
|
||||
|
||||
chip->ptp_clock_info.n_ext_ts = ptp_ops->n_ext_ts;
|
||||
chip->ptp_clock_info.n_per_out = 0;
|
||||
@ -413,6 +469,7 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
|
||||
}
|
||||
chip->ptp_clock_info.pin_config = chip->pin_config;
|
||||
|
||||
chip->ptp_clock_info.max_adj = MV88E6XXX_MAX_ADJ_PPB;
|
||||
chip->ptp_clock_info.adjfine = mv88e6xxx_ptp_adjfine;
|
||||
chip->ptp_clock_info.adjtime = mv88e6xxx_ptp_adjtime;
|
||||
chip->ptp_clock_info.gettime64 = mv88e6xxx_ptp_gettime;
|
||||
|
@ -149,6 +149,7 @@ void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip);
|
||||
ptp_clock_info)
|
||||
|
||||
extern const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops;
|
||||
extern const struct mv88e6xxx_ptp_ops mv88e6250_ptp_ops;
|
||||
extern const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops;
|
||||
|
||||
#else /* !CONFIG_NET_DSA_MV88E6XXX_PTP */
|
||||
@ -168,6 +169,7 @@ static inline void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip)
|
||||
}
|
||||
|
||||
static const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops = {};
|
||||
static const struct mv88e6xxx_ptp_ops mv88e6250_ptp_ops = {};
|
||||
static const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {};
|
||||
|
||||
#endif /* CONFIG_NET_DSA_MV88E6XXX_PTP */
|
||||
|
Loading…
Reference in New Issue
Block a user