Commit 71509614 authored by Hubert Feurstein's avatar Hubert Feurstein Committed by David S. Miller

net: dsa: mv88e6xxx: add PTP support for MV88E6250 family

This adds PTP support for the MV88E6250 family.
Signed-off-by: default avatarHubert Feurstein <h.feurstein@gmail.com>
Acked-by: default avatarRichard Cochran <richardcochran@gmail.com>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8858ccc8
...@@ -3538,6 +3538,8 @@ static const struct mv88e6xxx_ops mv88e6250_ops = { ...@@ -3538,6 +3538,8 @@ static const struct mv88e6xxx_ops mv88e6250_ops = {
.reset = mv88e6250_g1_reset, .reset = mv88e6250_g1_reset,
.vtu_getnext = mv88e6250_g1_vtu_getnext, .vtu_getnext = mv88e6250_g1_vtu_getnext,
.vtu_loadpurge = mv88e6250_g1_vtu_loadpurge, .vtu_loadpurge = mv88e6250_g1_vtu_loadpurge,
.avb_ops = &mv88e6352_avb_ops,
.ptp_ops = &mv88e6250_ptp_ops,
.phylink_validate = mv88e6065_phylink_validate, .phylink_validate = mv88e6065_phylink_validate,
}; };
...@@ -4334,6 +4336,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { ...@@ -4334,6 +4336,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.atu_move_port_mask = 0xf, .atu_move_port_mask = 0xf,
.dual_chip = true, .dual_chip = true,
.tag_protocol = DSA_TAG_PROTO_DSA, .tag_protocol = DSA_TAG_PROTO_DSA,
.ptp_support = true,
.ops = &mv88e6250_ops, .ops = &mv88e6250_ops,
}, },
...@@ -4379,6 +4382,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { ...@@ -4379,6 +4382,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.atu_move_port_mask = 0xf, .atu_move_port_mask = 0xf,
.dual_chip = true, .dual_chip = true,
.tag_protocol = DSA_TAG_PROTO_DSA, .tag_protocol = DSA_TAG_PROTO_DSA,
.ptp_support = true,
.ops = &mv88e6250_ops, .ops = &mv88e6250_ops,
}, },
......
...@@ -539,6 +539,10 @@ struct mv88e6xxx_ptp_ops { ...@@ -539,6 +539,10 @@ struct mv88e6xxx_ptp_ops {
int arr1_sts_reg; int arr1_sts_reg;
int dep_sts_reg; int dep_sts_reg;
u32 rx_filters; u32 rx_filters;
u32 cc_shift;
u32 cc_mult;
u32 cc_mult_num;
u32 cc_mult_dem;
}; };
#define STATS_TYPE_PORT BIT(0) #define STATS_TYPE_PORT BIT(0)
......
...@@ -15,11 +15,31 @@ ...@@ -15,11 +15,31 @@
#include "hwtstamp.h" #include "hwtstamp.h"
#include "ptp.h" #include "ptp.h"
/* Raw timestamps are in units of 8-ns clock periods. */ #define MV88E6XXX_MAX_ADJ_PPB 1000000
#define CC_SHIFT 28
#define CC_MULT (8 << CC_SHIFT) /* Family MV88E6250:
#define CC_MULT_NUM (1 << 9) * Raw timestamps are in units of 10-ns clock periods.
#define CC_MULT_DEM 15625ULL *
* 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) #define TAI_EVENT_WORK_INTERVAL msecs_to_jiffies(100)
...@@ -179,6 +199,7 @@ static void mv88e6352_tai_event_work(struct work_struct *ugly) ...@@ -179,6 +199,7 @@ static void mv88e6352_tai_event_work(struct work_struct *ugly)
static int mv88e6xxx_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) static int mv88e6xxx_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
{ {
struct mv88e6xxx_chip *chip = ptp_to_chip(ptp); struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
int neg_adj = 0; int neg_adj = 0;
u32 diff, mult; u32 diff, mult;
u64 adj; u64 adj;
...@@ -187,10 +208,11 @@ static int mv88e6xxx_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) ...@@ -187,10 +208,11 @@ static int mv88e6xxx_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
neg_adj = 1; neg_adj = 1;
scaled_ppm = -scaled_ppm; 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; adj *= scaled_ppm;
diff = div_u64(adj, CC_MULT_DEM); diff = div_u64(adj, ptp_ops->cc_mult_dem);
mv88e6xxx_reg_lock(chip); mv88e6xxx_reg_lock(chip);
...@@ -324,6 +346,37 @@ const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops = { ...@@ -324,6 +346,37 @@ const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops = {
(1 << HWTSTAMP_FILTER_PTP_V2_EVENT) | (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
(1 << HWTSTAMP_FILTER_PTP_V2_SYNC) | (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
(1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ), (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 = { const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {
...@@ -347,6 +400,10 @@ 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_EVENT) |
(1 << HWTSTAMP_FILTER_PTP_V2_SYNC) | (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
(1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ), (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) static u64 mv88e6xxx_ptp_clock_read(const struct cyclecounter *cc)
...@@ -384,8 +441,8 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip) ...@@ -384,8 +441,8 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
memset(&chip->tstamp_cc, 0, sizeof(chip->tstamp_cc)); memset(&chip->tstamp_cc, 0, sizeof(chip->tstamp_cc));
chip->tstamp_cc.read = mv88e6xxx_ptp_clock_read; chip->tstamp_cc.read = mv88e6xxx_ptp_clock_read;
chip->tstamp_cc.mask = CYCLECOUNTER_MASK(32); chip->tstamp_cc.mask = CYCLECOUNTER_MASK(32);
chip->tstamp_cc.mult = CC_MULT; chip->tstamp_cc.mult = ptp_ops->cc_mult;
chip->tstamp_cc.shift = CC_SHIFT; chip->tstamp_cc.shift = ptp_ops->cc_shift;
timecounter_init(&chip->tstamp_tc, &chip->tstamp_cc, timecounter_init(&chip->tstamp_tc, &chip->tstamp_cc,
ktime_to_ns(ktime_get_real())); ktime_to_ns(ktime_get_real()));
...@@ -397,7 +454,6 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip) ...@@ -397,7 +454,6 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
chip->ptp_clock_info.owner = THIS_MODULE; chip->ptp_clock_info.owner = THIS_MODULE;
snprintf(chip->ptp_clock_info.name, sizeof(chip->ptp_clock_info.name), snprintf(chip->ptp_clock_info.name, sizeof(chip->ptp_clock_info.name),
"%s", dev_name(chip->dev)); "%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_ext_ts = ptp_ops->n_ext_ts;
chip->ptp_clock_info.n_per_out = 0; chip->ptp_clock_info.n_per_out = 0;
...@@ -413,6 +469,7 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip) ...@@ -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.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.adjfine = mv88e6xxx_ptp_adjfine;
chip->ptp_clock_info.adjtime = mv88e6xxx_ptp_adjtime; chip->ptp_clock_info.adjtime = mv88e6xxx_ptp_adjtime;
chip->ptp_clock_info.gettime64 = mv88e6xxx_ptp_gettime; chip->ptp_clock_info.gettime64 = mv88e6xxx_ptp_gettime;
......
...@@ -149,6 +149,7 @@ void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip); ...@@ -149,6 +149,7 @@ void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip);
ptp_clock_info) ptp_clock_info)
extern const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops; 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; extern const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops;
#else /* !CONFIG_NET_DSA_MV88E6XXX_PTP */ #else /* !CONFIG_NET_DSA_MV88E6XXX_PTP */
...@@ -168,6 +169,7 @@ static inline void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip) ...@@ -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 mv88e6165_ptp_ops = {};
static const struct mv88e6xxx_ptp_ops mv88e6250_ptp_ops = {};
static const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {}; static const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {};
#endif /* CONFIG_NET_DSA_MV88E6XXX_PTP */ #endif /* CONFIG_NET_DSA_MV88E6XXX_PTP */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment