From 35e872ae6330e72c1b6045c021314b32a4a047de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20S=C3=B8rensen?= Date: Fri, 27 Jun 2014 12:05:29 +0200 Subject: [PATCH 1/5] dp83640: Program pulsewidth2 values of perout triggers 0 and 1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Periodic output triggers 0 and 1 of the dp83640 has a programmable duty-cycle which is controlled by the Pulsewidth2 field of the trigger data register. This field is not documented in the datasheet, but it is described in the "PHYTER Software Development Guide" section 3.1.4.1. Failing to set the field can result in unstable/no trigger output. Add programming of the Pulsewidth2 field, setting it to the same value as the Pulsewidth field for a 50% duty cycle. Signed-off-by: Stefan Sørensen Signed-off-by: David S. Miller --- drivers/net/phy/dp83640.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index 6a999e6814a07..fcd50b77999f1 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -353,6 +353,11 @@ static int periodic_output(struct dp83640_clock *clock, ext_write(0, phydev, PAGE4, PTP_TDR, sec >> 16); /* sec[31:16] */ ext_write(0, phydev, PAGE4, PTP_TDR, pwidth & 0xffff); /* ns[15:0] */ ext_write(0, phydev, PAGE4, PTP_TDR, pwidth >> 16); /* ns[31:16] */ + /* Triggers 0 and 1 has programmable pulsewidth2 */ + if (trigger < 2) { + ext_write(0, phydev, PAGE4, PTP_TDR, pwidth & 0xffff); + ext_write(0, phydev, PAGE4, PTP_TDR, pwidth >> 16); + } /*enable trigger*/ val &= ~TRIG_LOAD; From ad01577aeb92d7cc72bb945aeb28def3749065da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20S=C3=B8rensen?= Date: Fri, 27 Jun 2014 12:05:30 +0200 Subject: [PATCH 2/5] dp83640: Increase supported perout pins to 7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch increases the number of supported periodic output pins from 1 to 7. The last pin is reserved for sync. Signed-off-by: Stefan Sørensen Signed-off-by: David S. Miller --- drivers/net/phy/dp83640.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index fcd50b77999f1..eabecff9b740a 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -40,6 +40,7 @@ #define LAYER2 0x01 #define MAX_RXTS 64 #define N_EXT_TS 6 +#define N_PER_OUT 7 #define PSF_PTPVER 2 #define PSF_EVNT 0x4000 #define PSF_RX 0x2000 @@ -47,7 +48,6 @@ #define EXT_EVENT 1 #define CAL_EVENT 7 #define CAL_TRIGGER 7 -#define PER_TRIGGER 6 #define DP83640_N_PINS 12 #define MII_DP83640_MICR 0x11 @@ -300,23 +300,23 @@ static u64 phy2txts(struct phy_txts *p) } static int periodic_output(struct dp83640_clock *clock, - struct ptp_clock_request *clkreq, bool on) + struct ptp_clock_request *clkreq, bool on, + int trigger) { struct dp83640_private *dp83640 = clock->chosen; struct phy_device *phydev = dp83640->phydev; u32 sec, nsec, pwidth; - u16 gpio, ptp_trig, trigger, val; + u16 gpio, ptp_trig, val; if (on) { - gpio = 1 + ptp_find_pin(clock->ptp_clock, PTP_PF_PEROUT, 0); + gpio = 1 + ptp_find_pin(clock->ptp_clock, PTP_PF_PEROUT, + trigger); if (gpio < 1) return -EINVAL; } else { gpio = 0; } - trigger = PER_TRIGGER; - ptp_trig = TRIG_WR | (trigger & TRIG_CSEL_MASK) << TRIG_CSEL_SHIFT | (gpio & TRIG_GPIO_MASK) << TRIG_GPIO_SHIFT | @@ -496,9 +496,9 @@ static int ptp_dp83640_enable(struct ptp_clock_info *ptp, return 0; case PTP_CLK_REQ_PEROUT: - if (rq->perout.index != 0) + if (rq->perout.index >= N_PER_OUT) return -EINVAL; - return periodic_output(clock, rq, on); + return periodic_output(clock, rq, on, rq->perout.index); default: break; @@ -949,7 +949,7 @@ static void dp83640_clock_init(struct dp83640_clock *clock, struct mii_bus *bus) clock->caps.max_adj = 1953124; clock->caps.n_alarm = 0; clock->caps.n_ext_ts = N_EXT_TS; - clock->caps.n_per_out = 1; + clock->caps.n_per_out = N_PER_OUT; clock->caps.n_pins = DP83640_N_PINS; clock->caps.pps = 0; clock->caps.adjfreq = ptp_dp83640_adjfreq; From 6f39eb87de043ce778f584f4ae1b23c6db415a33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20S=C3=B8rensen?= Date: Fri, 27 Jun 2014 12:05:31 +0200 Subject: [PATCH 3/5] dp83640: Verify calibration pin assignment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This constraints the pin assignment to not allow the calibration function to be reassigned and only allow reassigning the calibratin pin if only one phy is connected. Signed-off-by: Stefan Sørensen Signed-off-by: David S. Miller --- drivers/net/phy/dp83640.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index eabecff9b740a..ab4811242458e 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -510,6 +510,16 @@ static int ptp_dp83640_enable(struct ptp_clock_info *ptp, static int ptp_dp83640_verify(struct ptp_clock_info *ptp, unsigned int pin, enum ptp_pin_function func, unsigned int chan) { + struct dp83640_clock *clock = + container_of(ptp, struct dp83640_clock, caps); + + if (clock->caps.pin_config[pin].func == PTP_PF_PHYSYNC && + !list_empty(&clock->phylist)) + return 1; + + if (func == PTP_PF_PHYSYNC) + return 1; + return 0; } From e0155950f01d26c1ae82b99d13e05b2127c7b7ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20S=C3=B8rensen?= Date: Fri, 27 Jun 2014 12:05:32 +0200 Subject: [PATCH 4/5] dp83640: Get calibration pin with ptp_find_pin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For consistency, use the ptp_find_pin function to get the calibration pin, not gpio_tab. Signed-off-by: Stefan Sørensen Signed-off-by: David S. Miller --- drivers/net/phy/dp83640.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index ab4811242458e..293ad064905d6 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -609,7 +609,11 @@ static void recalibrate(struct dp83640_clock *clock) u16 cal_gpio, cfg0, evnt, ptp_trig, trigger, val; trigger = CAL_TRIGGER; - cal_gpio = gpio_tab[CALIBRATE_GPIO]; + cal_gpio = 1 + ptp_find_pin(clock->ptp_clock, PTP_PF_PHYSYNC, 0); + if (cal_gpio < 1) { + pr_err("PHY calibration pin not avaible - PHY is not calibrated."); + return; + } mutex_lock(&clock->extreg_lock); From 72df7a7244c0d99414cbc1fd57c5cfeae964d3c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20S=C3=B8rensen?= Date: Fri, 27 Jun 2014 12:05:33 +0200 Subject: [PATCH 5/5] ptp: Allow reassigning calibration pin function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ptp pin function programming does not allow calibration pin to change function. This is problematic on hardware that uses the default calibration pin for other purposes. Removing this limitation does not impact calibration if userspace does not reprogram the calibration pin. Signed-off-by: Stefan Sørensen Signed-off-by: David S. Miller --- drivers/ptp/ptp_chardev.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c index 419056d7887ec..f8a76090cbca1 100644 --- a/drivers/ptp/ptp_chardev.c +++ b/drivers/ptp/ptp_chardev.c @@ -86,17 +86,12 @@ int ptp_set_pinfunc(struct ptp_clock *ptp, unsigned int pin, return -EINVAL; break; case PTP_PF_PHYSYNC: - pr_err("sorry, cannot reassign the calibration pin\n"); - return -EINVAL; + if (chan != 0) + return -EINVAL; default: return -EINVAL; } - if (pin2->func == PTP_PF_PHYSYNC) { - pr_err("sorry, cannot reprogram the calibration pin\n"); - return -EINVAL; - } - if (info->verify(info, pin, func, chan)) { pr_err("driver cannot use function %u on pin %u\n", func, chan); return -EOPNOTSUPP;