aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/igb
diff options
context:
space:
mode:
authorPatrick Ohly <patrick.ohly@intel.com>2009-02-12 00:03:41 -0500
committerDavid S. Miller <davem@davemloft.net>2009-02-16 02:13:25 -0500
commit38c845c7648ee354fd1d2fb8a7fbc352f2d3dcc3 (patch)
treeaa55b7d582dadb2735079f92f7fe246069647ae7 /drivers/net/igb
parentd24fff22d8dba13cc21034144f68f213415cb7c8 (diff)
igb: access to NIC time
Adds the register definitions and code to read the time register. Signed-off-by: John Ronciak <john.ronciak@intel.com> Signed-off-by: Patrick Ohly <patrick.ohly@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/igb')
-rw-r--r--drivers/net/igb/e1000_regs.h28
-rw-r--r--drivers/net/igb/igb.h4
-rw-r--r--drivers/net/igb/igb_main.c111
3 files changed, 143 insertions, 0 deletions
diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h
index 5038b73c78e9..64d95cd71f2e 100644
--- a/drivers/net/igb/e1000_regs.h
+++ b/drivers/net/igb/e1000_regs.h
@@ -75,6 +75,34 @@
75#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ 75#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */
76#define E1000_RDFPCQ(_n) (0x02430 + (0x4 * (_n))) 76#define E1000_RDFPCQ(_n) (0x02430 + (0x4 * (_n)))
77#define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */ 77#define E1000_FCRTV 0x02460 /* Flow Control Refresh Timer Value - RW */
78
79/* IEEE 1588 TIMESYNCH */
80#define E1000_TSYNCTXCTL 0x0B614
81#define E1000_TSYNCRXCTL 0x0B620
82#define E1000_TSYNCRXCFG 0x05F50
83
84#define E1000_SYSTIML 0x0B600
85#define E1000_SYSTIMH 0x0B604
86#define E1000_TIMINCA 0x0B608
87
88#define E1000_RXMTRL 0x0B634
89#define E1000_RXSTMPL 0x0B624
90#define E1000_RXSTMPH 0x0B628
91#define E1000_RXSATRL 0x0B62C
92#define E1000_RXSATRH 0x0B630
93
94#define E1000_TXSTMPL 0x0B618
95#define E1000_TXSTMPH 0x0B61C
96
97#define E1000_ETQF0 0x05CB0
98#define E1000_ETQF1 0x05CB4
99#define E1000_ETQF2 0x05CB8
100#define E1000_ETQF3 0x05CBC
101#define E1000_ETQF4 0x05CC0
102#define E1000_ETQF5 0x05CC4
103#define E1000_ETQF6 0x05CC8
104#define E1000_ETQF7 0x05CCC
105
78/* Split and Replication RX Control - RW */ 106/* Split and Replication RX Control - RW */
79/* 107/*
80 * Convenience macros 108 * Convenience macros
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index e507449b3cc2..797a9fe107ad 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -34,6 +34,8 @@
34#include "e1000_mac.h" 34#include "e1000_mac.h"
35#include "e1000_82575.h" 35#include "e1000_82575.h"
36 36
37#include <linux/clocksource.h>
38
37struct igb_adapter; 39struct igb_adapter;
38 40
39/* Interrupt defines */ 41/* Interrupt defines */
@@ -251,6 +253,8 @@ struct igb_adapter {
251 struct napi_struct napi; 253 struct napi_struct napi;
252 struct pci_dev *pdev; 254 struct pci_dev *pdev;
253 struct net_device_stats net_stats; 255 struct net_device_stats net_stats;
256 struct cyclecounter cycles;
257 struct timecounter clock;
254 258
255 /* structs defined in e1000_hw.h */ 259 /* structs defined in e1000_hw.h */
256 struct e1000_hw hw; 260 struct e1000_hw hw;
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index f8c2919bcec0..8b2ba4245090 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -175,6 +175,54 @@ MODULE_DESCRIPTION("Intel(R) Gigabit Ethernet Network Driver");
175MODULE_LICENSE("GPL"); 175MODULE_LICENSE("GPL");
176MODULE_VERSION(DRV_VERSION); 176MODULE_VERSION(DRV_VERSION);
177 177
178/**
179 * Scale the NIC clock cycle by a large factor so that
180 * relatively small clock corrections can be added or
181 * substracted at each clock tick. The drawbacks of a
182 * large factor are a) that the clock register overflows
183 * more quickly (not such a big deal) and b) that the
184 * increment per tick has to fit into 24 bits.
185 *
186 * Note that
187 * TIMINCA = IGB_TSYNC_CYCLE_TIME_IN_NANOSECONDS *
188 * IGB_TSYNC_SCALE
189 * TIMINCA += TIMINCA * adjustment [ppm] / 1e9
190 *
191 * The base scale factor is intentionally a power of two
192 * so that the division in %struct timecounter can be done with
193 * a shift.
194 */
195#define IGB_TSYNC_SHIFT (19)
196#define IGB_TSYNC_SCALE (1<<IGB_TSYNC_SHIFT)
197
198/**
199 * The duration of one clock cycle of the NIC.
200 *
201 * @todo This hard-coded value is part of the specification and might change
202 * in future hardware revisions. Add revision check.
203 */
204#define IGB_TSYNC_CYCLE_TIME_IN_NANOSECONDS 16
205
206#if (IGB_TSYNC_SCALE * IGB_TSYNC_CYCLE_TIME_IN_NANOSECONDS) >= (1<<24)
207# error IGB_TSYNC_SCALE and/or IGB_TSYNC_CYCLE_TIME_IN_NANOSECONDS are too large to fit into TIMINCA
208#endif
209
210/**
211 * igb_read_clock - read raw cycle counter (to be used by time counter)
212 */
213static cycle_t igb_read_clock(const struct cyclecounter *tc)
214{
215 struct igb_adapter *adapter =
216 container_of(tc, struct igb_adapter, cycles);
217 struct e1000_hw *hw = &adapter->hw;
218 u64 stamp;
219
220 stamp = rd32(E1000_SYSTIML);
221 stamp |= (u64)rd32(E1000_SYSTIMH) << 32ULL;
222
223 return stamp;
224}
225
178#ifdef DEBUG 226#ifdef DEBUG
179/** 227/**
180 * igb_get_hw_dev_name - return device name string 228 * igb_get_hw_dev_name - return device name string
@@ -185,6 +233,29 @@ char *igb_get_hw_dev_name(struct e1000_hw *hw)
185 struct igb_adapter *adapter = hw->back; 233 struct igb_adapter *adapter = hw->back;
186 return adapter->netdev->name; 234 return adapter->netdev->name;
187} 235}
236
237/**
238 * igb_get_time_str - format current NIC and system time as string
239 */
240static char *igb_get_time_str(struct igb_adapter *adapter,
241 char buffer[160])
242{
243 cycle_t hw = adapter->cycles.read(&adapter->cycles);
244 struct timespec nic = ns_to_timespec(timecounter_read(&adapter->clock));
245 struct timespec sys;
246 struct timespec delta;
247 getnstimeofday(&sys);
248
249 delta = timespec_sub(nic, sys);
250
251 sprintf(buffer,
252 "NIC %ld.%09lus, SYS %ld.%09lus, NIC-SYS %lds + %09luns",
253 (long)nic.tv_sec, nic.tv_nsec,
254 (long)sys.tv_sec, sys.tv_nsec,
255 (long)delta.tv_sec, delta.tv_nsec);
256
257 return buffer;
258}
188#endif 259#endif
189 260
190/** 261/**
@@ -1298,6 +1369,46 @@ static int __devinit igb_probe(struct pci_dev *pdev,
1298 } 1369 }
1299#endif 1370#endif
1300 1371
1372 /*
1373 * Initialize hardware timer: we keep it running just in case
1374 * that some program needs it later on.
1375 */
1376 memset(&adapter->cycles, 0, sizeof(adapter->cycles));
1377 adapter->cycles.read = igb_read_clock;
1378 adapter->cycles.mask = CLOCKSOURCE_MASK(64);
1379 adapter->cycles.mult = 1;
1380 adapter->cycles.shift = IGB_TSYNC_SHIFT;
1381 wr32(E1000_TIMINCA,
1382 (1<<24) |
1383 IGB_TSYNC_CYCLE_TIME_IN_NANOSECONDS * IGB_TSYNC_SCALE);
1384#if 0
1385 /*
1386 * Avoid rollover while we initialize by resetting the time counter.
1387 */
1388 wr32(E1000_SYSTIML, 0x00000000);
1389 wr32(E1000_SYSTIMH, 0x00000000);
1390#else
1391 /*
1392 * Set registers so that rollover occurs soon to test this.
1393 */
1394 wr32(E1000_SYSTIML, 0x00000000);
1395 wr32(E1000_SYSTIMH, 0xFF800000);
1396#endif
1397 wrfl();
1398 timecounter_init(&adapter->clock,
1399 &adapter->cycles,
1400 ktime_to_ns(ktime_get_real()));
1401
1402#ifdef DEBUG
1403 {
1404 char buffer[160];
1405 printk(KERN_DEBUG
1406 "igb: %s: hw %p initialized timer\n",
1407 igb_get_time_str(adapter, buffer),
1408 &adapter->hw);
1409 }
1410#endif
1411
1301 dev_info(&pdev->dev, "Intel(R) Gigabit Ethernet Network Connection\n"); 1412 dev_info(&pdev->dev, "Intel(R) Gigabit Ethernet Network Connection\n");
1302 /* print bus type/speed/width info */ 1413 /* print bus type/speed/width info */
1303 dev_info(&pdev->dev, "%s: (PCIe:%s:%s) %pM\n", 1414 dev_info(&pdev->dev, "%s: (PCIe:%s:%s) %pM\n",