Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6d2ac8ee authored by Andrew Lunn's avatar Andrew Lunn Committed by David S. Miller
Browse files

net: dsa: mv88e6xxx: Abstract PTP operations



The mv88e6165 family supports PTP, but its registers use a different
layout to the currently supported devices. Abstract accessing the PTP
registers into a set of ops, so making space for a second
implementation.

Signed-off-by: default avatarAndrew Lunn <andrew@lunn.ch>
Acked-by: default avatarRichard Cochran <richardcochran@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0725345e
Loading
Loading
Loading
Loading
+11 −0
Original line number Original line Diff line number Diff line
@@ -3134,6 +3134,8 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
	.vtu_getnext = mv88e6390_g1_vtu_getnext,
	.vtu_getnext = mv88e6390_g1_vtu_getnext,
	.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
	.vtu_loadpurge = mv88e6390_g1_vtu_loadpurge,
	.serdes_power = mv88e6390_serdes_power,
	.serdes_power = mv88e6390_serdes_power,
	.avb_ops = &mv88e6390_avb_ops,
	.ptp_ops = &mv88e6352_ptp_ops,
};
};


static const struct mv88e6xxx_ops mv88e6240_ops = {
static const struct mv88e6xxx_ops mv88e6240_ops = {
@@ -3176,6 +3178,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
	.serdes_power = mv88e6352_serdes_power,
	.serdes_power = mv88e6352_serdes_power,
	.gpio_ops = &mv88e6352_gpio_ops,
	.gpio_ops = &mv88e6352_gpio_ops,
	.avb_ops = &mv88e6352_avb_ops,
	.avb_ops = &mv88e6352_avb_ops,
	.ptp_ops = &mv88e6352_ptp_ops,
};
};


static const struct mv88e6xxx_ops mv88e6290_ops = {
static const struct mv88e6xxx_ops mv88e6290_ops = {
@@ -3215,6 +3218,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
	.serdes_power = mv88e6390_serdes_power,
	.serdes_power = mv88e6390_serdes_power,
	.gpio_ops = &mv88e6352_gpio_ops,
	.gpio_ops = &mv88e6352_gpio_ops,
	.avb_ops = &mv88e6390_avb_ops,
	.avb_ops = &mv88e6390_avb_ops,
	.ptp_ops = &mv88e6352_ptp_ops,
};
};


static const struct mv88e6xxx_ops mv88e6320_ops = {
static const struct mv88e6xxx_ops mv88e6320_ops = {
@@ -3253,6 +3257,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
	.vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
	.vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
	.gpio_ops = &mv88e6352_gpio_ops,
	.gpio_ops = &mv88e6352_gpio_ops,
	.avb_ops = &mv88e6352_avb_ops,
	.avb_ops = &mv88e6352_avb_ops,
	.ptp_ops = &mv88e6352_ptp_ops,
};
};


static const struct mv88e6xxx_ops mv88e6321_ops = {
static const struct mv88e6xxx_ops mv88e6321_ops = {
@@ -3289,6 +3294,7 @@ static const struct mv88e6xxx_ops mv88e6321_ops = {
	.vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
	.vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
	.gpio_ops = &mv88e6352_gpio_ops,
	.gpio_ops = &mv88e6352_gpio_ops,
	.avb_ops = &mv88e6352_avb_ops,
	.avb_ops = &mv88e6352_avb_ops,
	.ptp_ops = &mv88e6352_ptp_ops,
};
};


static const struct mv88e6xxx_ops mv88e6341_ops = {
static const struct mv88e6xxx_ops mv88e6341_ops = {
@@ -3329,6 +3335,7 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
	.gpio_ops = &mv88e6352_gpio_ops,
	.gpio_ops = &mv88e6352_gpio_ops,
	.avb_ops = &mv88e6390_avb_ops,
	.avb_ops = &mv88e6390_avb_ops,
	.ptp_ops = &mv88e6352_ptp_ops,
};
};


static const struct mv88e6xxx_ops mv88e6350_ops = {
static const struct mv88e6xxx_ops mv88e6350_ops = {
@@ -3402,6 +3409,7 @@ static const struct mv88e6xxx_ops mv88e6351_ops = {
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
	.vtu_getnext = mv88e6352_g1_vtu_getnext,
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
	.vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
	.avb_ops = &mv88e6352_avb_ops,
	.avb_ops = &mv88e6352_avb_ops,
	.ptp_ops = &mv88e6352_ptp_ops,
};
};


static const struct mv88e6xxx_ops mv88e6352_ops = {
static const struct mv88e6xxx_ops mv88e6352_ops = {
@@ -3444,6 +3452,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
	.serdes_power = mv88e6352_serdes_power,
	.serdes_power = mv88e6352_serdes_power,
	.gpio_ops = &mv88e6352_gpio_ops,
	.gpio_ops = &mv88e6352_gpio_ops,
	.avb_ops = &mv88e6352_avb_ops,
	.avb_ops = &mv88e6352_avb_ops,
	.ptp_ops = &mv88e6352_ptp_ops,
	.serdes_get_sset_count = mv88e6352_serdes_get_sset_count,
	.serdes_get_sset_count = mv88e6352_serdes_get_sset_count,
	.serdes_get_strings = mv88e6352_serdes_get_strings,
	.serdes_get_strings = mv88e6352_serdes_get_strings,
	.serdes_get_stats = mv88e6352_serdes_get_stats,
	.serdes_get_stats = mv88e6352_serdes_get_stats,
@@ -3488,6 +3497,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
	.serdes_power = mv88e6390_serdes_power,
	.serdes_power = mv88e6390_serdes_power,
	.gpio_ops = &mv88e6352_gpio_ops,
	.gpio_ops = &mv88e6352_gpio_ops,
	.avb_ops = &mv88e6390_avb_ops,
	.avb_ops = &mv88e6390_avb_ops,
	.ptp_ops = &mv88e6352_ptp_ops,
};
};


static const struct mv88e6xxx_ops mv88e6390x_ops = {
static const struct mv88e6xxx_ops mv88e6390x_ops = {
@@ -3529,6 +3539,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
	.serdes_power = mv88e6390_serdes_power,
	.serdes_power = mv88e6390_serdes_power,
	.gpio_ops = &mv88e6352_gpio_ops,
	.gpio_ops = &mv88e6352_gpio_ops,
	.avb_ops = &mv88e6390_avb_ops,
	.avb_ops = &mv88e6390_avb_ops,
	.ptp_ops = &mv88e6352_ptp_ops,
};
};


static const struct mv88e6xxx_info mv88e6xxx_table[] = {
static const struct mv88e6xxx_info mv88e6xxx_table[] = {
+14 −0
Original line number Original line Diff line number Diff line
@@ -155,6 +155,7 @@ struct mv88e6xxx_bus_ops;
struct mv88e6xxx_irq_ops;
struct mv88e6xxx_irq_ops;
struct mv88e6xxx_gpio_ops;
struct mv88e6xxx_gpio_ops;
struct mv88e6xxx_avb_ops;
struct mv88e6xxx_avb_ops;
struct mv88e6xxx_ptp_ops;


struct mv88e6xxx_irq {
struct mv88e6xxx_irq {
	u16 masked;
	u16 masked;
@@ -439,6 +440,9 @@ struct mv88e6xxx_ops {


	/* Remote Management Unit operations */
	/* Remote Management Unit operations */
	int (*rmu_disable)(struct mv88e6xxx_chip *chip);
	int (*rmu_disable)(struct mv88e6xxx_chip *chip);

	/* Precision Time Protocol operations */
	const struct mv88e6xxx_ptp_ops *ptp_ops;
};
};


struct mv88e6xxx_irq_ops {
struct mv88e6xxx_irq_ops {
@@ -486,6 +490,16 @@ struct mv88e6xxx_avb_ops {
	int (*tai_write)(struct mv88e6xxx_chip *chip, int addr, u16 data);
	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 n_ext_ts;
};

#define STATS_TYPE_PORT		BIT(0)
#define STATS_TYPE_PORT		BIT(0)
#define STATS_TYPE_BANK0	BIT(1)
#define STATS_TYPE_BANK0	BIT(1)
#define STATS_TYPE_BANK1	BIT(2)
#define STATS_TYPE_BANK1	BIT(2)
+38 −17
Original line number Original line Diff line number Diff line
@@ -50,7 +50,7 @@ static int mv88e6xxx_tai_write(struct mv88e6xxx_chip *chip, int addr, u16 data)
}
}


/* TODO: places where this are called should be using pinctrl */
/* 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 func, int input)
{
{
	int err;
	int err;
@@ -65,7 +65,7 @@ static int mv88e6xxx_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 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);
	struct mv88e6xxx_chip *chip = cc_to_chip(cc);
	u16 phc_time[2];
	u16 phc_time[2];
@@ -79,13 +79,13 @@ static u64 mv88e6xxx_ptp_clock_read(const struct cyclecounter *cc)
		return ((u32)phc_time[1] << 16) | phc_time[0];
		return ((u32)phc_time[1] << 16) | phc_time[0];
}
}


/* mv88e6xxx_config_eventcap - configure TAI event capture
/* mv88e6352_config_eventcap - configure TAI event capture
 * @event: PTP_CLOCK_PPS (internal) or PTP_CLOCK_EXTTS (external)
 * @event: PTP_CLOCK_PPS (internal) or PTP_CLOCK_EXTTS (external)
 * @rising: zero for falling-edge trigger, else rising-edge trigger
 * @rising: zero for falling-edge trigger, else rising-edge trigger
 *
 *
 * This will also reset the capture sequence counter.
 * 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)
				     int rising)
{
{
	u16 global_config;
	u16 global_config;
@@ -118,7 +118,7 @@ static int mv88e6xxx_config_eventcap(struct mv88e6xxx_chip *chip, int event,
	return err;
	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 delayed_work *dw = to_delayed_work(ugly);
	struct mv88e6xxx_chip *chip = dw_tai_event_to_chip(dw);
	struct mv88e6xxx_chip *chip = dw_tai_event_to_chip(dw);
@@ -232,7 +232,7 @@ static int mv88e6xxx_ptp_settime(struct ptp_clock_info *ptp,
	return 0;
	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)
				      struct ptp_clock_request *rq, int on)
{
{
	int rising = (rq->extts.flags & PTP_RISING_EDGE);
	int rising = (rq->extts.flags & PTP_RISING_EDGE);
@@ -250,18 +250,18 @@ static int mv88e6xxx_ptp_enable_extts(struct mv88e6xxx_chip *chip,
	if (on) {
	if (on) {
		func = MV88E6352_G2_SCRATCH_GPIO_PCTL_EVREQ;
		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)
		if (err)
			goto out;
			goto out;


		schedule_delayed_work(&chip->tai_event_work,
		schedule_delayed_work(&chip->tai_event_work,
				      TAI_EVENT_WORK_INTERVAL);
				      TAI_EVENT_WORK_INTERVAL);


		err = mv88e6xxx_config_eventcap(chip, PTP_CLOCK_EXTTS, rising);
		err = mv88e6352_config_eventcap(chip, PTP_CLOCK_EXTTS, rising);
	} else {
	} else {
		func = MV88E6352_G2_SCRATCH_GPIO_PCTL_GPIO;
		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);
		cancel_delayed_work_sync(&chip->tai_event_work);
	}
	}
@@ -272,20 +272,20 @@ static int mv88e6xxx_ptp_enable_extts(struct mv88e6xxx_chip *chip,
	return err;
	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 ptp_clock_request *rq, int on)
{
{
	struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
	struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);


	switch (rq->type) {
	switch (rq->type) {
	case PTP_CLK_REQ_EXTTS:
	case PTP_CLK_REQ_EXTTS:
		return mv88e6xxx_ptp_enable_extts(chip, rq, on);
		return mv88e6352_ptp_enable_extts(chip, rq, on);
	default:
	default:
		return -EOPNOTSUPP;
		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)
				enum ptp_pin_function func, unsigned int chan)
{
{
	switch (func) {
	switch (func) {
@@ -299,6 +299,24 @@ static int mv88e6xxx_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin,
	return 0;
	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,
	.n_ext_ts = 1,
};

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
/* 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.
 * seconds; this task forces periodic reads so that we don't miss any.
 */
 */
@@ -317,6 +335,7 @@ static void mv88e6xxx_ptp_overflow_check(struct work_struct *work)


int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
{
{
	const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
	int i;
	int i;


	/* Set up the cycle counter */
	/* Set up the cycle counter */
@@ -330,14 +349,15 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
			 ktime_to_ns(ktime_get_real()));
			 ktime_to_ns(ktime_get_real()));


	INIT_DELAYED_WORK(&chip->overflow_work, mv88e6xxx_ptp_overflow_check);
	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;
	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),
		 dev_name(chip->dev));
		 dev_name(chip->dev));
	chip->ptp_clock_info.max_adj	= 1000000;
	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_per_out	= 0;
	chip->ptp_clock_info.n_pins	= mv88e6xxx_num_gpio(chip);
	chip->ptp_clock_info.n_pins	= mv88e6xxx_num_gpio(chip);
	chip->ptp_clock_info.pps	= 0;
	chip->ptp_clock_info.pps	= 0;
@@ -355,8 +375,8 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
	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;
	chip->ptp_clock_info.settime64	= mv88e6xxx_ptp_settime;
	chip->ptp_clock_info.settime64	= mv88e6xxx_ptp_settime;
	chip->ptp_clock_info.enable	= mv88e6xxx_ptp_enable;
	chip->ptp_clock_info.enable	= ptp_ops->ptp_enable;
	chip->ptp_clock_info.verify	= mv88e6xxx_ptp_verify;
	chip->ptp_clock_info.verify	= ptp_ops->ptp_verify;
	chip->ptp_clock_info.do_aux_work = mv88e6xxx_hwtstamp_work;
	chip->ptp_clock_info.do_aux_work = mv88e6xxx_hwtstamp_work;


	chip->ptp_clock = ptp_clock_register(&chip->ptp_clock_info, chip->dev);
	chip->ptp_clock = ptp_clock_register(&chip->ptp_clock_info, chip->dev);
@@ -373,6 +393,7 @@ void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip)
{
{
	if (chip->ptp_clock) {
	if (chip->ptp_clock) {
		cancel_delayed_work_sync(&chip->overflow_work);
		cancel_delayed_work_sync(&chip->overflow_work);
		if (chip->info->ops->ptp_ops->event_work)
			cancel_delayed_work_sync(&chip->tai_event_work);
			cancel_delayed_work_sync(&chip->tai_event_work);


		ptp_clock_unregister(chip->ptp_clock);
		ptp_clock_unregister(chip->ptp_clock);
+4 −0
Original line number Original line Diff line number Diff line
@@ -87,6 +87,8 @@ void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip);
#define ptp_to_chip(ptp) container_of(ptp, struct mv88e6xxx_chip,	\
#define ptp_to_chip(ptp) container_of(ptp, struct mv88e6xxx_chip,	\
				      ptp_clock_info)
				      ptp_clock_info)


extern const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops;

#else /* !CONFIG_NET_DSA_MV88E6XXX_PTP */
#else /* !CONFIG_NET_DSA_MV88E6XXX_PTP */


static inline long mv88e6xxx_hwtstamp_work(struct ptp_clock_info *ptp)
static inline long mv88e6xxx_hwtstamp_work(struct ptp_clock_info *ptp)
@@ -103,6 +105,8 @@ static inline void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip)
{
{
}
}


static const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {};

#endif /* CONFIG_NET_DSA_MV88E6XXX_PTP */
#endif /* CONFIG_NET_DSA_MV88E6XXX_PTP */


#endif /* _MV88E6XXX_PTP_H */
#endif /* _MV88E6XXX_PTP_H */