net: dsa: mv88e6xxx: read cycle counter period from hardware
Instead of relying on a fixed mapping of hardware family to cycle
counter frequency, pull this information from the
MV88E6XXX_TAI_CLOCK_PERIOD register.
This lets us support switches whose cycle counter frequencies depend on
board design.
Fixes: de776d0d31
("net: dsa: mv88e6xxx: add support for mv88e6393x family")
Suggested-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Shenghao Yang <me@shenghaoyang.info>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
parent
67af86afff
commit
7e3c18097a
@ -409,6 +409,7 @@ struct mv88e6xxx_chip {
|
|||||||
struct cyclecounter tstamp_cc;
|
struct cyclecounter tstamp_cc;
|
||||||
struct timecounter tstamp_tc;
|
struct timecounter tstamp_tc;
|
||||||
struct delayed_work overflow_work;
|
struct delayed_work overflow_work;
|
||||||
|
const struct mv88e6xxx_cc_coeffs *cc_coeffs;
|
||||||
|
|
||||||
struct ptp_clock *ptp_clock;
|
struct ptp_clock *ptp_clock;
|
||||||
struct ptp_clock_info ptp_clock_info;
|
struct ptp_clock_info ptp_clock_info;
|
||||||
@ -732,7 +733,6 @@ 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;
|
||||||
const struct mv88e6xxx_cc_coeffs *cc_coeffs;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mv88e6xxx_pcs_ops {
|
struct mv88e6xxx_pcs_ops {
|
||||||
|
@ -32,10 +32,10 @@ struct mv88e6xxx_cc_coeffs {
|
|||||||
* simplifies to
|
* simplifies to
|
||||||
* clkadj = scaled_ppm * 2^7 / 5^5
|
* clkadj = scaled_ppm * 2^7 / 5^5
|
||||||
*/
|
*/
|
||||||
#define MV88E6250_CC_SHIFT 28
|
#define MV88E6XXX_CC_10NS_SHIFT 28
|
||||||
static const struct mv88e6xxx_cc_coeffs mv88e6250_cc_coeffs = {
|
static const struct mv88e6xxx_cc_coeffs mv88e6xxx_cc_10ns_coeffs = {
|
||||||
.cc_shift = MV88E6250_CC_SHIFT,
|
.cc_shift = MV88E6XXX_CC_10NS_SHIFT,
|
||||||
.cc_mult = 10 << MV88E6250_CC_SHIFT,
|
.cc_mult = 10 << MV88E6XXX_CC_10NS_SHIFT,
|
||||||
.cc_mult_num = 1 << 7,
|
.cc_mult_num = 1 << 7,
|
||||||
.cc_mult_dem = 3125ULL,
|
.cc_mult_dem = 3125ULL,
|
||||||
};
|
};
|
||||||
@ -47,10 +47,10 @@ static const struct mv88e6xxx_cc_coeffs mv88e6250_cc_coeffs = {
|
|||||||
* simplifies to
|
* simplifies to
|
||||||
* clkadj = scaled_ppm * 2^9 / 5^6
|
* clkadj = scaled_ppm * 2^9 / 5^6
|
||||||
*/
|
*/
|
||||||
#define MV88E6XXX_CC_SHIFT 28
|
#define MV88E6XXX_CC_8NS_SHIFT 28
|
||||||
static const struct mv88e6xxx_cc_coeffs mv88e6xxx_cc_coeffs = {
|
static const struct mv88e6xxx_cc_coeffs mv88e6xxx_cc_8ns_coeffs = {
|
||||||
.cc_shift = MV88E6XXX_CC_SHIFT,
|
.cc_shift = MV88E6XXX_CC_8NS_SHIFT,
|
||||||
.cc_mult = 8 << MV88E6XXX_CC_SHIFT,
|
.cc_mult = 8 << MV88E6XXX_CC_8NS_SHIFT,
|
||||||
.cc_mult_num = 1 << 9,
|
.cc_mult_num = 1 << 9,
|
||||||
.cc_mult_dem = 15625ULL
|
.cc_mult_dem = 15625ULL
|
||||||
};
|
};
|
||||||
@ -96,6 +96,31 @@ static int mv88e6352_set_gpio_func(struct mv88e6xxx_chip *chip, int pin,
|
|||||||
return chip->info->ops->gpio_ops->set_pctl(chip, pin, func);
|
return chip->info->ops->gpio_ops->set_pctl(chip, pin, func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct mv88e6xxx_cc_coeffs *
|
||||||
|
mv88e6xxx_cc_coeff_get(struct mv88e6xxx_chip *chip)
|
||||||
|
{
|
||||||
|
u16 period_ps;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = mv88e6xxx_tai_read(chip, MV88E6XXX_TAI_CLOCK_PERIOD, &period_ps, 1);
|
||||||
|
if (err) {
|
||||||
|
dev_err(chip->dev, "failed to read cycle counter period: %d\n",
|
||||||
|
err);
|
||||||
|
return ERR_PTR(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (period_ps) {
|
||||||
|
case 8000:
|
||||||
|
return &mv88e6xxx_cc_8ns_coeffs;
|
||||||
|
case 10000:
|
||||||
|
return &mv88e6xxx_cc_10ns_coeffs;
|
||||||
|
default:
|
||||||
|
dev_err(chip->dev, "unexpected cycle counter period of %u ps\n",
|
||||||
|
period_ps);
|
||||||
|
return ERR_PTR(-ENODEV);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static u64 mv88e6352_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);
|
struct mv88e6xxx_chip *chip = cc_to_chip(cc);
|
||||||
@ -217,7 +242,6 @@ out:
|
|||||||
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;
|
||||||
@ -227,10 +251,10 @@ static int mv88e6xxx_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
|
|||||||
scaled_ppm = -scaled_ppm;
|
scaled_ppm = -scaled_ppm;
|
||||||
}
|
}
|
||||||
|
|
||||||
mult = ptp_ops->cc_coeffs->cc_mult;
|
mult = chip->cc_coeffs->cc_mult;
|
||||||
adj = ptp_ops->cc_coeffs->cc_mult_num;
|
adj = chip->cc_coeffs->cc_mult_num;
|
||||||
adj *= scaled_ppm;
|
adj *= scaled_ppm;
|
||||||
diff = div_u64(adj, ptp_ops->cc_coeffs->cc_mult_dem);
|
diff = div_u64(adj, chip->cc_coeffs->cc_mult_dem);
|
||||||
|
|
||||||
mv88e6xxx_reg_lock(chip);
|
mv88e6xxx_reg_lock(chip);
|
||||||
|
|
||||||
@ -377,7 +401,6 @@ 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_coeffs = &mv88e6xxx_cc_coeffs
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct mv88e6xxx_ptp_ops mv88e6250_ptp_ops = {
|
const struct mv88e6xxx_ptp_ops mv88e6250_ptp_ops = {
|
||||||
@ -401,7 +424,6 @@ const struct mv88e6xxx_ptp_ops mv88e6250_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_coeffs = &mv88e6250_cc_coeffs,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {
|
const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {
|
||||||
@ -425,7 +447,6 @@ 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_coeffs = &mv88e6xxx_cc_coeffs,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct mv88e6xxx_ptp_ops mv88e6390_ptp_ops = {
|
const struct mv88e6xxx_ptp_ops mv88e6390_ptp_ops = {
|
||||||
@ -450,7 +471,6 @@ const struct mv88e6xxx_ptp_ops mv88e6390_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_coeffs = &mv88e6xxx_cc_coeffs,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static u64 mv88e6xxx_ptp_clock_read(const struct cyclecounter *cc)
|
static u64 mv88e6xxx_ptp_clock_read(const struct cyclecounter *cc)
|
||||||
@ -485,11 +505,15 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Set up the cycle counter */
|
/* Set up the cycle counter */
|
||||||
|
chip->cc_coeffs = mv88e6xxx_cc_coeff_get(chip);
|
||||||
|
if (IS_ERR(chip->cc_coeffs))
|
||||||
|
return PTR_ERR(chip->cc_coeffs);
|
||||||
|
|
||||||
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 = ptp_ops->cc_coeffs->cc_mult;
|
chip->tstamp_cc.mult = chip->cc_coeffs->cc_mult;
|
||||||
chip->tstamp_cc.shift = ptp_ops->cc_coeffs->cc_shift;
|
chip->tstamp_cc.shift = chip->cc_coeffs->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()));
|
||||||
|
Loading…
Reference in New Issue
Block a user