aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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
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')
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c61
-rw-r--r--drivers/net/ethernet/broadcom/tg3.h11
2 files changed, 68 insertions, 4 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,
diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h
index cd63d1189aae..2e0f3d34ea5d 100644
--- a/drivers/net/ethernet/broadcom/tg3.h
+++ b/drivers/net/ethernet/broadcom/tg3.h
@@ -1818,12 +1818,21 @@
1818#define TG3_EAV_REF_CLCK_CTL 0x00006908 1818#define TG3_EAV_REF_CLCK_CTL 0x00006908
1819#define TG3_EAV_REF_CLCK_CTL_STOP 0x00000002 1819#define TG3_EAV_REF_CLCK_CTL_STOP 0x00000002
1820#define TG3_EAV_REF_CLCK_CTL_RESUME 0x00000004 1820#define TG3_EAV_REF_CLCK_CTL_RESUME 0x00000004
1821#define TG3_EAV_CTL_TSYNC_GPIO_MASK (0x3 << 16)
1822#define TG3_EAV_CTL_TSYNC_WDOG0 (1 << 17)
1823
1824#define TG3_EAV_WATCHDOG0_LSB 0x00006918
1825#define TG3_EAV_WATCHDOG0_MSB 0x0000691c
1826#define TG3_EAV_WATCHDOG0_EN (1 << 31)
1827#define TG3_EAV_WATCHDOG_MSB_MASK 0x7fffffff
1828
1821#define TG3_EAV_REF_CLK_CORRECT_CTL 0x00006928 1829#define TG3_EAV_REF_CLK_CORRECT_CTL 0x00006928
1822#define TG3_EAV_REF_CLK_CORRECT_EN (1 << 31) 1830#define TG3_EAV_REF_CLK_CORRECT_EN (1 << 31)
1823#define TG3_EAV_REF_CLK_CORRECT_NEG (1 << 30) 1831#define TG3_EAV_REF_CLK_CORRECT_NEG (1 << 30)
1824 1832
1825#define TG3_EAV_REF_CLK_CORRECT_MASK 0xffffff 1833#define TG3_EAV_REF_CLK_CORRECT_MASK 0xffffff
1826/* 0x690c --> 0x7000 unused */ 1834
1835/* 0x692c --> 0x7000 unused */
1827 1836
1828/* NVRAM Control registers */ 1837/* NVRAM Control registers */
1829#define NVRAM_CMD 0x00007000 1838#define NVRAM_CMD 0x00007000