ixf1010.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. /* $Date: 2005/11/12 02:13:49 $ $RCSfile: ixf1010.c,v $ $Revision: 1.36 $ */
  2. #include "gmac.h"
  3. #include "elmer0.h"
  4. /* Update fast changing statistics every 15 seconds */
  5. #define STATS_TICK_SECS 15
  6. /* 30 minutes for full statistics update */
  7. #define MAJOR_UPDATE_TICKS (1800 / STATS_TICK_SECS)
  8. /*
  9. * The IXF1010 can handle frames up to 16383 bytes but it's optimized for
  10. * frames up to 9831 (0x2667) bytes, so we limit jumbo frame size to this.
  11. * This length includes ethernet header and FCS.
  12. */
  13. #define MAX_FRAME_SIZE 0x2667
  14. /* MAC registers */
  15. enum {
  16. /* Per-port registers */
  17. REG_MACADDR_LOW = 0,
  18. REG_MACADDR_HIGH = 0x4,
  19. REG_FDFC_TYPE = 0xC,
  20. REG_FC_TX_TIMER_VALUE = 0x1c,
  21. REG_IPG_RX_TIME1 = 0x28,
  22. REG_IPG_RX_TIME2 = 0x2c,
  23. REG_IPG_TX_TIME = 0x30,
  24. REG_PAUSE_THRES = 0x38,
  25. REG_MAX_FRAME_SIZE = 0x3c,
  26. REG_RGMII_SPEED = 0x40,
  27. REG_FC_ENABLE = 0x48,
  28. REG_DISCARD_CTRL_FRAMES = 0x54,
  29. REG_DIVERSE_CONFIG = 0x60,
  30. REG_RX_FILTER = 0x64,
  31. REG_MC_ADDR_LOW = 0x68,
  32. REG_MC_ADDR_HIGH = 0x6c,
  33. REG_RX_OCTETS_OK = 0x80,
  34. REG_RX_OCTETS_BAD = 0x84,
  35. REG_RX_UC_PKTS = 0x88,
  36. REG_RX_MC_PKTS = 0x8c,
  37. REG_RX_BC_PKTS = 0x90,
  38. REG_RX_FCS_ERR = 0xb0,
  39. REG_RX_TAGGED = 0xb4,
  40. REG_RX_DATA_ERR = 0xb8,
  41. REG_RX_ALIGN_ERR = 0xbc,
  42. REG_RX_LONG_ERR = 0xc0,
  43. REG_RX_JABBER_ERR = 0xc4,
  44. REG_RX_PAUSE_FRAMES = 0xc8,
  45. REG_RX_UNKNOWN_CTRL_FRAMES = 0xcc,
  46. REG_RX_VERY_LONG_ERR = 0xd0,
  47. REG_RX_RUNT_ERR = 0xd4,
  48. REG_RX_SHORT_ERR = 0xd8,
  49. REG_RX_SYMBOL_ERR = 0xe4,
  50. REG_TX_OCTETS_OK = 0x100,
  51. REG_TX_OCTETS_BAD = 0x104,
  52. REG_TX_UC_PKTS = 0x108,
  53. REG_TX_MC_PKTS = 0x10c,
  54. REG_TX_BC_PKTS = 0x110,
  55. REG_TX_EXCESSIVE_LEN_DROP = 0x14c,
  56. REG_TX_UNDERRUN = 0x150,
  57. REG_TX_TAGGED = 0x154,
  58. REG_TX_PAUSE_FRAMES = 0x15C,
  59. /* Global registers */
  60. REG_PORT_ENABLE = 0x1400,
  61. REG_JTAG_ID = 0x1430,
  62. RX_FIFO_HIGH_WATERMARK_BASE = 0x1600,
  63. RX_FIFO_LOW_WATERMARK_BASE = 0x1628,
  64. RX_FIFO_FRAMES_REMOVED_BASE = 0x1650,
  65. REG_RX_ERR_DROP = 0x167c,
  66. REG_RX_FIFO_OVERFLOW_EVENT = 0x1680,
  67. TX_FIFO_HIGH_WATERMARK_BASE = 0x1800,
  68. TX_FIFO_LOW_WATERMARK_BASE = 0x1828,
  69. TX_FIFO_XFER_THRES_BASE = 0x1850,
  70. REG_TX_FIFO_OVERFLOW_EVENT = 0x1878,
  71. REG_TX_FIFO_OOS_EVENT = 0x1884,
  72. TX_FIFO_FRAMES_REMOVED_BASE = 0x1888,
  73. REG_SPI_RX_BURST = 0x1c00,
  74. REG_SPI_RX_TRAINING = 0x1c04,
  75. REG_SPI_RX_CALENDAR = 0x1c08,
  76. REG_SPI_TX_SYNC = 0x1c0c
  77. };
  78. enum { /* RMON registers */
  79. REG_RxOctetsTotalOK = 0x80,
  80. REG_RxOctetsBad = 0x84,
  81. REG_RxUCPkts = 0x88,
  82. REG_RxMCPkts = 0x8c,
  83. REG_RxBCPkts = 0x90,
  84. REG_RxJumboPkts = 0xac,
  85. REG_RxFCSErrors = 0xb0,
  86. REG_RxDataErrors = 0xb8,
  87. REG_RxAlignErrors = 0xbc,
  88. REG_RxLongErrors = 0xc0,
  89. REG_RxJabberErrors = 0xc4,
  90. REG_RxPauseMacControlCounter = 0xc8,
  91. REG_RxVeryLongErrors = 0xd0,
  92. REG_RxRuntErrors = 0xd4,
  93. REG_RxShortErrors = 0xd8,
  94. REG_RxSequenceErrors = 0xe0,
  95. REG_RxSymbolErrors = 0xe4,
  96. REG_TxOctetsTotalOK = 0x100,
  97. REG_TxOctetsBad = 0x104,
  98. REG_TxUCPkts = 0x108,
  99. REG_TxMCPkts = 0x10c,
  100. REG_TxBCPkts = 0x110,
  101. REG_TxJumboPkts = 0x12C,
  102. REG_TxTotalCollisions = 0x134,
  103. REG_TxExcessiveLengthDrop = 0x14c,
  104. REG_TxUnderrun = 0x150,
  105. REG_TxCRCErrors = 0x158,
  106. REG_TxPauseFrames = 0x15c
  107. };
  108. enum {
  109. DIVERSE_CONFIG_PAD_ENABLE = 0x80,
  110. DIVERSE_CONFIG_CRC_ADD = 0x40
  111. };
  112. #define MACREG_BASE 0
  113. #define MACREG(mac, mac_reg) ((mac)->instance->mac_base + (mac_reg))
  114. struct _cmac_instance {
  115. u32 mac_base;
  116. u32 index;
  117. u32 version;
  118. u32 ticks;
  119. };
  120. static void disable_port(struct cmac *mac)
  121. {
  122. u32 val;
  123. t1_tpi_read(mac->adapter, REG_PORT_ENABLE, &val);
  124. val &= ~(1 << mac->instance->index);
  125. t1_tpi_write(mac->adapter, REG_PORT_ENABLE, val);
  126. }
  127. #define RMON_UPDATE(mac, name, stat_name) \
  128. t1_tpi_read((mac)->adapter, MACREG(mac, REG_##name), &val); \
  129. (mac)->stats.stat_name += val;
  130. /*
  131. * Read the current values of the RMON counters and add them to the cumulative
  132. * port statistics. The HW RMON counters are cleared by this operation.
  133. */
  134. static void port_stats_update(struct cmac *mac)
  135. {
  136. u32 val;
  137. /* Rx stats */
  138. RMON_UPDATE(mac, RxOctetsTotalOK, RxOctetsOK);
  139. RMON_UPDATE(mac, RxOctetsBad, RxOctetsBad);
  140. RMON_UPDATE(mac, RxUCPkts, RxUnicastFramesOK);
  141. RMON_UPDATE(mac, RxMCPkts, RxMulticastFramesOK);
  142. RMON_UPDATE(mac, RxBCPkts, RxBroadcastFramesOK);
  143. RMON_UPDATE(mac, RxJumboPkts, RxJumboFramesOK);
  144. RMON_UPDATE(mac, RxFCSErrors, RxFCSErrors);
  145. RMON_UPDATE(mac, RxAlignErrors, RxAlignErrors);
  146. RMON_UPDATE(mac, RxLongErrors, RxFrameTooLongErrors);
  147. RMON_UPDATE(mac, RxVeryLongErrors, RxFrameTooLongErrors);
  148. RMON_UPDATE(mac, RxPauseMacControlCounter, RxPauseFrames);
  149. RMON_UPDATE(mac, RxDataErrors, RxDataErrors);
  150. RMON_UPDATE(mac, RxJabberErrors, RxJabberErrors);
  151. RMON_UPDATE(mac, RxRuntErrors, RxRuntErrors);
  152. RMON_UPDATE(mac, RxShortErrors, RxRuntErrors);
  153. RMON_UPDATE(mac, RxSequenceErrors, RxSequenceErrors);
  154. RMON_UPDATE(mac, RxSymbolErrors, RxSymbolErrors);
  155. /* Tx stats (skip collision stats as we are full-duplex only) */
  156. RMON_UPDATE(mac, TxOctetsTotalOK, TxOctetsOK);
  157. RMON_UPDATE(mac, TxOctetsBad, TxOctetsBad);
  158. RMON_UPDATE(mac, TxUCPkts, TxUnicastFramesOK);
  159. RMON_UPDATE(mac, TxMCPkts, TxMulticastFramesOK);
  160. RMON_UPDATE(mac, TxBCPkts, TxBroadcastFramesOK);
  161. RMON_UPDATE(mac, TxJumboPkts, TxJumboFramesOK);
  162. RMON_UPDATE(mac, TxPauseFrames, TxPauseFrames);
  163. RMON_UPDATE(mac, TxExcessiveLengthDrop, TxLengthErrors);
  164. RMON_UPDATE(mac, TxUnderrun, TxUnderrun);
  165. RMON_UPDATE(mac, TxCRCErrors, TxFCSErrors);
  166. }
  167. /* No-op interrupt operation as this MAC does not support interrupts */
  168. static int mac_intr_op(struct cmac *mac)
  169. {
  170. return 0;
  171. }
  172. /* Expect MAC address to be in network byte order. */
  173. static int mac_set_address(struct cmac *mac, u8 addr[6])
  174. {
  175. u32 addr_lo, addr_hi;
  176. addr_lo = addr[2];
  177. addr_lo = (addr_lo << 8) | addr[3];
  178. addr_lo = (addr_lo << 8) | addr[4];
  179. addr_lo = (addr_lo << 8) | addr[5];
  180. addr_hi = addr[0];
  181. addr_hi = (addr_hi << 8) | addr[1];
  182. t1_tpi_write(mac->adapter, MACREG(mac, REG_MACADDR_LOW), addr_lo);
  183. t1_tpi_write(mac->adapter, MACREG(mac, REG_MACADDR_HIGH), addr_hi);
  184. return 0;
  185. }
  186. static int mac_get_address(struct cmac *mac, u8 addr[6])
  187. {
  188. u32 addr_lo, addr_hi;
  189. t1_tpi_read(mac->adapter, MACREG(mac, REG_MACADDR_LOW), &addr_lo);
  190. t1_tpi_read(mac->adapter, MACREG(mac, REG_MACADDR_HIGH), &addr_hi);
  191. addr[0] = (u8) (addr_hi >> 8);
  192. addr[1] = (u8) addr_hi;
  193. addr[2] = (u8) (addr_lo >> 24);
  194. addr[3] = (u8) (addr_lo >> 16);
  195. addr[4] = (u8) (addr_lo >> 8);
  196. addr[5] = (u8) addr_lo;
  197. return 0;
  198. }
  199. /* This is intended to reset a port, not the whole MAC */
  200. static int mac_reset(struct cmac *mac)
  201. {
  202. return 0;
  203. }
  204. static int mac_set_rx_mode(struct cmac *mac, struct t1_rx_mode *rm)
  205. {
  206. u32 val, new_mode;
  207. adapter_t *adapter = mac->adapter;
  208. u32 addr_lo, addr_hi;
  209. u8 *addr;
  210. t1_tpi_read(adapter, MACREG(mac, REG_RX_FILTER), &val);
  211. new_mode = val & ~7;
  212. if (!t1_rx_mode_promisc(rm) && mac->instance->version > 0)
  213. new_mode |= 1; /* only set if version > 0 due to erratum */
  214. if (!t1_rx_mode_promisc(rm) && !t1_rx_mode_allmulti(rm)
  215. && t1_rx_mode_mc_cnt(rm) <= 1)
  216. new_mode |= 2;
  217. if (new_mode != val)
  218. t1_tpi_write(adapter, MACREG(mac, REG_RX_FILTER), new_mode);
  219. switch (t1_rx_mode_mc_cnt(rm)) {
  220. case 0:
  221. t1_tpi_write(adapter, MACREG(mac, REG_MC_ADDR_LOW), 0);
  222. t1_tpi_write(adapter, MACREG(mac, REG_MC_ADDR_HIGH), 0);
  223. break;
  224. case 1:
  225. addr = t1_get_next_mcaddr(rm);
  226. addr_lo = (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) |
  227. addr[5];
  228. addr_hi = (addr[0] << 8) | addr[1];
  229. t1_tpi_write(adapter, MACREG(mac, REG_MC_ADDR_LOW), addr_lo);
  230. t1_tpi_write(adapter, MACREG(mac, REG_MC_ADDR_HIGH), addr_hi);
  231. break;
  232. default:
  233. break;
  234. }
  235. return 0;
  236. }
  237. static int mac_set_mtu(struct cmac *mac, int mtu)
  238. {
  239. /* MAX_FRAME_SIZE inludes header + FCS, mtu doesn't */
  240. if (mtu > (MAX_FRAME_SIZE - 14 - 4)) return -EINVAL;
  241. t1_tpi_write(mac->adapter, MACREG(mac, REG_MAX_FRAME_SIZE),
  242. mtu + 14 + 4);
  243. return 0;
  244. }
  245. static int mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex,
  246. int fc)
  247. {
  248. u32 val;
  249. if (speed >= 0 && speed != SPEED_100 && speed != SPEED_1000)
  250. return -1;
  251. if (duplex >= 0 && duplex != DUPLEX_FULL)
  252. return -1;
  253. if (speed >= 0) {
  254. val = speed == SPEED_100 ? 1 : 2;
  255. t1_tpi_write(mac->adapter, MACREG(mac, REG_RGMII_SPEED), val);
  256. }
  257. t1_tpi_read(mac->adapter, MACREG(mac, REG_FC_ENABLE), &val);
  258. val &= ~3;
  259. if (fc & PAUSE_RX)
  260. val |= 1;
  261. if (fc & PAUSE_TX)
  262. val |= 2;
  263. t1_tpi_write(mac->adapter, MACREG(mac, REG_FC_ENABLE), val);
  264. return 0;
  265. }
  266. static int mac_get_speed_duplex_fc(struct cmac *mac, int *speed, int *duplex,
  267. int *fc)
  268. {
  269. u32 val;
  270. if (duplex)
  271. *duplex = DUPLEX_FULL;
  272. if (speed) {
  273. t1_tpi_read(mac->adapter, MACREG(mac, REG_RGMII_SPEED),
  274. &val);
  275. *speed = (val & 2) ? SPEED_1000 : SPEED_100;
  276. }
  277. if (fc) {
  278. t1_tpi_read(mac->adapter, MACREG(mac, REG_FC_ENABLE), &val);
  279. *fc = 0;
  280. if (val & 1)
  281. *fc |= PAUSE_RX;
  282. if (val & 2)
  283. *fc |= PAUSE_TX;
  284. }
  285. return 0;
  286. }
  287. static void enable_port(struct cmac *mac)
  288. {
  289. u32 val;
  290. u32 index = mac->instance->index;
  291. adapter_t *adapter = mac->adapter;
  292. t1_tpi_read(adapter, MACREG(mac, REG_DIVERSE_CONFIG), &val);
  293. val |= DIVERSE_CONFIG_CRC_ADD | DIVERSE_CONFIG_PAD_ENABLE;
  294. t1_tpi_write(adapter, MACREG(mac, REG_DIVERSE_CONFIG), val);
  295. if (mac->instance->version > 0)
  296. t1_tpi_write(adapter, MACREG(mac, REG_RX_FILTER), 3);
  297. else /* Don't enable unicast address filtering due to IXF1010 bug */
  298. t1_tpi_write(adapter, MACREG(mac, REG_RX_FILTER), 2);
  299. t1_tpi_read(adapter, REG_RX_ERR_DROP, &val);
  300. val |= (1 << index);
  301. t1_tpi_write(adapter, REG_RX_ERR_DROP, val);
  302. /*
  303. * Clear the port RMON registers by adding their current values to the
  304. * cumulatice port stats and then clearing the stats. Really.
  305. */
  306. port_stats_update(mac);
  307. memset(&mac->stats, 0, sizeof(struct cmac_statistics));
  308. mac->instance->ticks = 0;
  309. t1_tpi_read(adapter, REG_PORT_ENABLE, &val);
  310. val |= (1 << index);
  311. t1_tpi_write(adapter, REG_PORT_ENABLE, val);
  312. index <<= 2;
  313. if (is_T2(adapter)) {
  314. /* T204: set the Fifo water level & threshold */
  315. t1_tpi_write(adapter, RX_FIFO_HIGH_WATERMARK_BASE + index, 0x740);
  316. t1_tpi_write(adapter, RX_FIFO_LOW_WATERMARK_BASE + index, 0x730);
  317. t1_tpi_write(adapter, TX_FIFO_HIGH_WATERMARK_BASE + index, 0x600);
  318. t1_tpi_write(adapter, TX_FIFO_LOW_WATERMARK_BASE + index, 0x1d0);
  319. t1_tpi_write(adapter, TX_FIFO_XFER_THRES_BASE + index, 0x1100);
  320. } else {
  321. /*
  322. * Set the TX Fifo Threshold to 0x400 instead of 0x100 to work around
  323. * Underrun problem. Intel has blessed this solution.
  324. */
  325. t1_tpi_write(adapter, TX_FIFO_XFER_THRES_BASE + index, 0x400);
  326. }
  327. }
  328. /* IXF1010 ports do not have separate enables for TX and RX */
  329. static int mac_enable(struct cmac *mac, int which)
  330. {
  331. if (which & (MAC_DIRECTION_RX | MAC_DIRECTION_TX))
  332. enable_port(mac);
  333. return 0;
  334. }
  335. static int mac_disable(struct cmac *mac, int which)
  336. {
  337. if (which & (MAC_DIRECTION_RX | MAC_DIRECTION_TX))
  338. disable_port(mac);
  339. return 0;
  340. }
  341. /*
  342. * This function is called periodically to accumulate the current values of the
  343. * RMON counters into the port statistics. Since the counters are only 32 bits
  344. * some of them can overflow in less than a minute at GigE speeds, so this
  345. * function should be called every 30 seconds or so.
  346. *
  347. * To cut down on reading costs we update only the octet counters at each tick
  348. * and do a full update at major ticks, which can be every 30 minutes or more.
  349. */
  350. static const struct cmac_statistics *mac_update_statistics(struct cmac *mac,
  351. int flag)
  352. {
  353. if (flag == MAC_STATS_UPDATE_FULL ||
  354. MAJOR_UPDATE_TICKS <= mac->instance->ticks) {
  355. port_stats_update(mac);
  356. mac->instance->ticks = 0;
  357. } else {
  358. u32 val;
  359. RMON_UPDATE(mac, RxOctetsTotalOK, RxOctetsOK);
  360. RMON_UPDATE(mac, TxOctetsTotalOK, TxOctetsOK);
  361. mac->instance->ticks++;
  362. }
  363. return &mac->stats;
  364. }
  365. static void mac_destroy(struct cmac *mac)
  366. {
  367. kfree(mac);
  368. }
  369. static struct cmac_ops ixf1010_ops = {
  370. .destroy = mac_destroy,
  371. .reset = mac_reset,
  372. .interrupt_enable = mac_intr_op,
  373. .interrupt_disable = mac_intr_op,
  374. .interrupt_clear = mac_intr_op,
  375. .enable = mac_enable,
  376. .disable = mac_disable,
  377. .set_mtu = mac_set_mtu,
  378. .set_rx_mode = mac_set_rx_mode,
  379. .set_speed_duplex_fc = mac_set_speed_duplex_fc,
  380. .get_speed_duplex_fc = mac_get_speed_duplex_fc,
  381. .statistics_update = mac_update_statistics,
  382. .macaddress_get = mac_get_address,
  383. .macaddress_set = mac_set_address,
  384. };
  385. static int ixf1010_mac_reset(adapter_t *adapter)
  386. {
  387. u32 val;
  388. t1_tpi_read(adapter, A_ELMER0_GPO, &val);
  389. if ((val & 1) != 0) {
  390. val &= ~1;
  391. t1_tpi_write(adapter, A_ELMER0_GPO, val);
  392. udelay(2);
  393. }
  394. val |= 1;
  395. t1_tpi_write(adapter, A_ELMER0_GPO, val);
  396. udelay(2);
  397. t1_tpi_write(adapter, REG_PORT_ENABLE, 0);
  398. return 0;
  399. }
  400. static struct cmac *ixf1010_mac_create(adapter_t *adapter, int index)
  401. {
  402. struct cmac *mac;
  403. u32 val;
  404. if (index > 9) return NULL;
  405. mac = kzalloc(sizeof(*mac) + sizeof(cmac_instance), GFP_KERNEL);
  406. if (!mac) return NULL;
  407. mac->ops = &ixf1010_ops;
  408. mac->instance = (cmac_instance *)(mac + 1);
  409. mac->instance->mac_base = MACREG_BASE + (index * 0x200);
  410. mac->instance->index = index;
  411. mac->adapter = adapter;
  412. mac->instance->ticks = 0;
  413. t1_tpi_read(adapter, REG_JTAG_ID, &val);
  414. mac->instance->version = val >> 28;
  415. return mac;
  416. }
  417. struct gmac t1_ixf1010_ops = {
  418. STATS_TICK_SECS,
  419. ixf1010_mac_create,
  420. ixf1010_mac_reset
  421. };