aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/broadcom/tg3.c
diff options
context:
space:
mode:
authorNithin Sujir <nsujir@broadcom.com>2013-07-29 16:58:38 -0400
committerDavid S. Miller <davem@davemloft.net>2013-07-30 02:38:52 -0400
commit92e6457d4cf68ef69bc4f98330c93e198df06a43 (patch)
treea60ad7edf04f1881225b8e4eb04fd3f394221c24 /drivers/net/ethernet/broadcom/tg3.c
parent4c305fa2cbe2a85c34899763fcefb843c87b591d (diff)
tg3: Enable support for timesync gpio output
The PTP_CAPABLE tg3 devices have a gpio output that is toggled when the free running counter matches a watchdog value. This patch adds support to set the watchdog and enable this feature. Since the output is controlled via bits in the EAV_REF_CLCK_CTL register, we have to read-modify-write it when we stop/resume. Cc: Richard Cochran <richardcochran@gmail.com> Signed-off-by: Nithin Nayak Sujir <nsujir@broadcom.com> Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/broadcom/tg3.c')
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c61
1 files changed, 58 insertions, 3 deletions
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 935170757786..f077c8f5baa1 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -6093,10 +6093,12 @@ static u64 tg3_refclk_read(struct tg3 *tp)
6093/* tp->lock must be held */ 6093/* tp->lock must be held */
6094static void tg3_refclk_write(struct tg3 *tp, u64 newval) 6094static void tg3_refclk_write(struct tg3 *tp, u64 newval)
6095{ 6095{
6096 tw32(TG3_EAV_REF_CLCK_CTL, TG3_EAV_REF_CLCK_CTL_STOP); 6096 u32 clock_ctl = tr32(TG3_EAV_REF_CLCK_CTL);
6097
6098 tw32(TG3_EAV_REF_CLCK_CTL, clock_ctl | TG3_EAV_REF_CLCK_CTL_STOP);
6097 tw32(TG3_EAV_REF_CLCK_LSB, newval & 0xffffffff); 6099 tw32(TG3_EAV_REF_CLCK_LSB, newval & 0xffffffff);
6098 tw32(TG3_EAV_REF_CLCK_MSB, newval >> 32); 6100 tw32(TG3_EAV_REF_CLCK_MSB, newval >> 32);
6099 tw32_f(TG3_EAV_REF_CLCK_CTL, TG3_EAV_REF_CLCK_CTL_RESUME); 6101 tw32_f(TG3_EAV_REF_CLCK_CTL, clock_ctl | TG3_EAV_REF_CLCK_CTL_RESUME);
6100} 6102}
6101 6103
6102static inline void tg3_full_lock(struct tg3 *tp, int irq_sync); 6104static inline void tg3_full_lock(struct tg3 *tp, int irq_sync);
@@ -6212,6 +6214,59 @@ static int tg3_ptp_settime(struct ptp_clock_info *ptp,
6212static int tg3_ptp_enable(struct ptp_clock_info *ptp, 6214static int tg3_ptp_enable(struct ptp_clock_info *ptp,
6213 struct ptp_clock_request *rq, int on) 6215 struct ptp_clock_request *rq, int on)
6214{ 6216{
6217 struct tg3 *tp = container_of(ptp, struct tg3, ptp_info);
6218 u32 clock_ctl;
6219 int rval = 0;
6220
6221 switch (rq->type) {
6222 case PTP_CLK_REQ_PEROUT:
6223 if (rq->perout.index != 0)
6224 return -EINVAL;
6225
6226 tg3_full_lock(tp, 0);
6227 clock_ctl = tr32(TG3_EAV_REF_CLCK_CTL);
6228 clock_ctl &= ~TG3_EAV_CTL_TSYNC_GPIO_MASK;
6229
6230 if (on) {
6231 u64 nsec;
6232
6233 nsec = rq->perout.start.sec * 1000000000ULL +
6234 rq->perout.start.nsec;
6235
6236 if (rq->perout.period.sec || rq->perout.period.nsec) {
6237 netdev_warn(tp->dev,
6238 "Device supports only a one-shot timesync output, period must be 0\n");
6239 rval = -EINVAL;
6240 goto err_out;
6241 }
6242
6243 if (nsec & (1ULL << 63)) {
6244 netdev_warn(tp->dev,
6245 "Start value (nsec) is over limit. Maximum size of start is only 63 bits\n");
6246 rval = -EINVAL;
6247 goto err_out;
6248 }
6249
6250 tw32(TG3_EAV_WATCHDOG0_LSB, (nsec & 0xffffffff));
6251 tw32(TG3_EAV_WATCHDOG0_MSB,
6252 TG3_EAV_WATCHDOG0_EN |
6253 ((nsec >> 32) & TG3_EAV_WATCHDOG_MSB_MASK));
6254
6255 tw32(TG3_EAV_REF_CLCK_CTL,
6256 clock_ctl | TG3_EAV_CTL_TSYNC_WDOG0);
6257 } else {
6258 tw32(TG3_EAV_WATCHDOG0_MSB, 0);
6259 tw32(TG3_EAV_REF_CLCK_CTL, clock_ctl);
6260 }
6261
6262err_out:
6263 tg3_full_unlock(tp);
6264 return rval;
6265
6266 default:
6267 break;
6268 }
6269
6215 return -EOPNOTSUPP; 6270 return -EOPNOTSUPP;
6216} 6271}
6217 6272
@@ -6221,7 +6276,7 @@ static const struct ptp_clock_info tg3_ptp_caps = {
6221 .max_adj = 250000000, 6276 .max_adj = 250000000,
6222 .n_alarm = 0, 6277 .n_alarm = 0,
6223 .n_ext_ts = 0, 6278 .n_ext_ts = 0,
6224 .n_per_out = 0, 6279 .n_per_out = 1,
6225 .pps = 0, 6280 .pps = 0,
6226 .adjfreq = tg3_ptp_adjfreq, 6281 .adjfreq = tg3_ptp_adjfreq,
6227 .adjtime = tg3_ptp_adjtime, 6282 .adjtime = tg3_ptp_adjtime,