aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ks8842.c
diff options
context:
space:
mode:
authorDavid J. Choi <david.choi@micrel.com>2010-07-13 13:09:19 -0400
committerDavid S. Miller <davem@davemloft.net>2010-07-13 13:13:49 -0400
commit28bd620c7a1244e59459d6293ca11f162e0a67b9 (patch)
treea0ff06027d762346eb81aae4a835c56df0938133 /drivers/net/ks8842.c
parent242647bcf8464860f173f3d4d4ab3490d3558518 (diff)
drivers/net: Add Micrel KS8841/42 support to ks8842 driver
Body of the explanation: -support 16bit and 32bit bus width. -add device reset for ks8842/8841 Micrel device. -set 100Mbps as a default for Micrel device. -set MAC address in both MAC/Switch layer with different sequence for Micrel device, as mentioned in data sheet. -use private data to set options both 16/32bit bus width and Micrel device/ Timberdale(FPGA). -update Kconfig in order to put more information about ks8842 device. Signed-off-by: David J. Choi <david.choi@micrel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ks8842.c')
-rw-r--r--drivers/net/ks8842.c174
1 files changed, 129 insertions, 45 deletions
diff --git a/drivers/net/ks8842.c b/drivers/net/ks8842.c
index 0be92613acf0..ee69dea69be8 100644
--- a/drivers/net/ks8842.c
+++ b/drivers/net/ks8842.c
@@ -18,6 +18,7 @@
18 18
19/* Supports: 19/* Supports:
20 * The Micrel KS8842 behind the timberdale FPGA 20 * The Micrel KS8842 behind the timberdale FPGA
21 * The genuine Micrel KS8841/42 device with ISA 16/32bit bus interface
21 */ 22 */
22 23
23#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 24#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -114,9 +115,14 @@
114#define REG_P1CR4 0x02 115#define REG_P1CR4 0x02
115#define REG_P1SR 0x04 116#define REG_P1SR 0x04
116 117
118/* flags passed by platform_device for configuration */
119#define MICREL_KS884X 0x01 /* 0=Timeberdale(FPGA), 1=Micrel */
120#define KS884X_16BIT 0x02 /* 1=16bit, 0=32bit */
121
117struct ks8842_adapter { 122struct ks8842_adapter {
118 void __iomem *hw_addr; 123 void __iomem *hw_addr;
119 int irq; 124 int irq;
125 unsigned long conf_flags; /* copy of platform_device config */
120 struct tasklet_struct tasklet; 126 struct tasklet_struct tasklet;
121 spinlock_t lock; /* spinlock to be interrupt safe */ 127 spinlock_t lock; /* spinlock to be interrupt safe */
122 struct work_struct timeout_work; 128 struct work_struct timeout_work;
@@ -192,15 +198,21 @@ static inline u32 ks8842_read32(struct ks8842_adapter *adapter, u16 bank,
192 198
193static void ks8842_reset(struct ks8842_adapter *adapter) 199static void ks8842_reset(struct ks8842_adapter *adapter)
194{ 200{
195 /* The KS8842 goes haywire when doing softare reset 201 if (adapter->conf_flags & MICREL_KS884X) {
196 * a work around in the timberdale IP is implemented to 202 ks8842_write16(adapter, 3, 1, REG_GRR);
197 * do a hardware reset instead 203 msleep(10);
198 ks8842_write16(adapter, 3, 1, REG_GRR); 204 iowrite16(0, adapter->hw_addr + REG_GRR);
199 msleep(10); 205 } else {
200 iowrite16(0, adapter->hw_addr + REG_GRR); 206 /* The KS8842 goes haywire when doing softare reset
201 */ 207 * a work around in the timberdale IP is implemented to
202 iowrite32(0x1, adapter->hw_addr + REG_TIMB_RST); 208 * do a hardware reset instead
203 msleep(20); 209 ks8842_write16(adapter, 3, 1, REG_GRR);
210 msleep(10);
211 iowrite16(0, adapter->hw_addr + REG_GRR);
212 */
213 iowrite32(0x1, adapter->hw_addr + REG_TIMB_RST);
214 msleep(20);
215 }
204} 216}
205 217
206static void ks8842_update_link_status(struct net_device *netdev, 218static void ks8842_update_link_status(struct net_device *netdev,
@@ -269,8 +281,10 @@ static void ks8842_reset_hw(struct ks8842_adapter *adapter)
269 281
270 /* restart port auto-negotiation */ 282 /* restart port auto-negotiation */
271 ks8842_enable_bits(adapter, 49, 1 << 13, REG_P1CR4); 283 ks8842_enable_bits(adapter, 49, 1 << 13, REG_P1CR4);
272 /* only advertise 10Mbps */ 284
273 ks8842_clear_bits(adapter, 49, 3 << 2, REG_P1CR4); 285 if (!(adapter->conf_flags & MICREL_KS884X))
286 /* only advertise 10Mbps */
287 ks8842_clear_bits(adapter, 49, 3 << 2, REG_P1CR4);
274 288
275 /* Enable the transmitter */ 289 /* Enable the transmitter */
276 ks8842_enable_tx(adapter); 290 ks8842_enable_tx(adapter);
@@ -296,13 +310,28 @@ static void ks8842_read_mac_addr(struct ks8842_adapter *adapter, u8 *dest)
296 for (i = 0; i < ETH_ALEN; i++) 310 for (i = 0; i < ETH_ALEN; i++)
297 dest[ETH_ALEN - i - 1] = ks8842_read8(adapter, 2, REG_MARL + i); 311 dest[ETH_ALEN - i - 1] = ks8842_read8(adapter, 2, REG_MARL + i);
298 312
299 /* make sure the switch port uses the same MAC as the QMU */ 313 if (adapter->conf_flags & MICREL_KS884X) {
300 mac = ks8842_read16(adapter, 2, REG_MARL); 314 /*
301 ks8842_write16(adapter, 39, mac, REG_MACAR1); 315 the sequence of saving mac addr between MAC and Switch is
302 mac = ks8842_read16(adapter, 2, REG_MARM); 316 different.
303 ks8842_write16(adapter, 39, mac, REG_MACAR2); 317 */
304 mac = ks8842_read16(adapter, 2, REG_MARH); 318
305 ks8842_write16(adapter, 39, mac, REG_MACAR3); 319 mac = ks8842_read16(adapter, 2, REG_MARL);
320 ks8842_write16(adapter, 39, mac, REG_MACAR3);
321 mac = ks8842_read16(adapter, 2, REG_MARM);
322 ks8842_write16(adapter, 39, mac, REG_MACAR2);
323 mac = ks8842_read16(adapter, 2, REG_MARH);
324 ks8842_write16(adapter, 39, mac, REG_MACAR1);
325 } else {
326
327 /* make sure the switch port uses the same MAC as the QMU */
328 mac = ks8842_read16(adapter, 2, REG_MARL);
329 ks8842_write16(adapter, 39, mac, REG_MACAR1);
330 mac = ks8842_read16(adapter, 2, REG_MARM);
331 ks8842_write16(adapter, 39, mac, REG_MACAR2);
332 mac = ks8842_read16(adapter, 2, REG_MARH);
333 ks8842_write16(adapter, 39, mac, REG_MACAR3);
334 }
306} 335}
307 336
308static void ks8842_write_mac_addr(struct ks8842_adapter *adapter, u8 *mac) 337static void ks8842_write_mac_addr(struct ks8842_adapter *adapter, u8 *mac)
@@ -313,8 +342,25 @@ static void ks8842_write_mac_addr(struct ks8842_adapter *adapter, u8 *mac)
313 spin_lock_irqsave(&adapter->lock, flags); 342 spin_lock_irqsave(&adapter->lock, flags);
314 for (i = 0; i < ETH_ALEN; i++) { 343 for (i = 0; i < ETH_ALEN; i++) {
315 ks8842_write8(adapter, 2, mac[ETH_ALEN - i - 1], REG_MARL + i); 344 ks8842_write8(adapter, 2, mac[ETH_ALEN - i - 1], REG_MARL + i);
316 ks8842_write8(adapter, 39, mac[ETH_ALEN - i - 1], 345 if (!(adapter->conf_flags & MICREL_KS884X))
317 REG_MACAR1 + i); 346 ks8842_write8(adapter, 39, mac[ETH_ALEN - i - 1],
347 REG_MACAR1 + i);
348 }
349
350 if (adapter->conf_flags & MICREL_KS884X) {
351 /*
352 the sequence of saving mac addr between MAC and Switch is
353 different.
354 */
355
356 u16 mac;
357
358 mac = ks8842_read16(adapter, 2, REG_MARL);
359 ks8842_write16(adapter, 39, mac, REG_MACAR3);
360 mac = ks8842_read16(adapter, 2, REG_MARM);
361 ks8842_write16(adapter, 39, mac, REG_MACAR2);
362 mac = ks8842_read16(adapter, 2, REG_MARH);
363 ks8842_write16(adapter, 39, mac, REG_MACAR1);
318 } 364 }
319 spin_unlock_irqrestore(&adapter->lock, flags); 365 spin_unlock_irqrestore(&adapter->lock, flags);
320} 366}
@@ -328,8 +374,6 @@ static int ks8842_tx_frame(struct sk_buff *skb, struct net_device *netdev)
328{ 374{
329 struct ks8842_adapter *adapter = netdev_priv(netdev); 375 struct ks8842_adapter *adapter = netdev_priv(netdev);
330 int len = skb->len; 376 int len = skb->len;
331 u32 *ptr = (u32 *)skb->data;
332 u32 ctrl;
333 377
334 netdev_dbg(netdev, "%s: len %u head %p data %p tail %p end %p\n", 378 netdev_dbg(netdev, "%s: len %u head %p data %p tail %p end %p\n",
335 __func__, skb->len, skb->head, skb->data, 379 __func__, skb->len, skb->head, skb->data,
@@ -339,17 +383,34 @@ static int ks8842_tx_frame(struct sk_buff *skb, struct net_device *netdev)
339 if (ks8842_tx_fifo_space(adapter) < len + 8) 383 if (ks8842_tx_fifo_space(adapter) < len + 8)
340 return NETDEV_TX_BUSY; 384 return NETDEV_TX_BUSY;
341 385
342 /* the control word, enable IRQ, port 1 and the length */ 386 if (adapter->conf_flags & KS884X_16BIT) {
343 ctrl = 0x8000 | 0x100 | (len << 16); 387 u16 *ptr16 = (u16 *)skb->data;
344 ks8842_write32(adapter, 17, ctrl, REG_QMU_DATA_LO); 388 ks8842_write16(adapter, 17, 0x8000 | 0x100, REG_QMU_DATA_LO);
389 ks8842_write16(adapter, 17, (u16)len, REG_QMU_DATA_HI);
390 netdev->stats.tx_bytes += len;
391
392 /* copy buffer */
393 while (len > 0) {
394 iowrite16(*ptr16++, adapter->hw_addr + REG_QMU_DATA_LO);
395 iowrite16(*ptr16++, adapter->hw_addr + REG_QMU_DATA_HI);
396 len -= sizeof(u32);
397 }
398 } else {
399
400 u32 *ptr = (u32 *)skb->data;
401 u32 ctrl;
402 /* the control word, enable IRQ, port 1 and the length */
403 ctrl = 0x8000 | 0x100 | (len << 16);
404 ks8842_write32(adapter, 17, ctrl, REG_QMU_DATA_LO);
345 405
346 netdev->stats.tx_bytes += len; 406 netdev->stats.tx_bytes += len;
347 407
348 /* copy buffer */ 408 /* copy buffer */
349 while (len > 0) { 409 while (len > 0) {
350 iowrite32(*ptr, adapter->hw_addr + REG_QMU_DATA_LO); 410 iowrite32(*ptr, adapter->hw_addr + REG_QMU_DATA_LO);
351 len -= sizeof(u32); 411 len -= sizeof(u32);
352 ptr++; 412 ptr++;
413 }
353 } 414 }
354 415
355 /* enqueue packet */ 416 /* enqueue packet */
@@ -363,12 +424,23 @@ static int ks8842_tx_frame(struct sk_buff *skb, struct net_device *netdev)
363static void ks8842_rx_frame(struct net_device *netdev, 424static void ks8842_rx_frame(struct net_device *netdev,
364 struct ks8842_adapter *adapter) 425 struct ks8842_adapter *adapter)
365{ 426{
366 u32 status = ks8842_read32(adapter, 17, REG_QMU_DATA_LO); 427 u16 status16;
367 int len = (status >> 16) & 0x7ff; 428 u32 status;
429 int len;
368 430
369 status &= 0xffff; 431 if (adapter->conf_flags & KS884X_16BIT) {
370 432 status16 = ks8842_read16(adapter, 17, REG_QMU_DATA_LO);
371 netdev_dbg(netdev, "%s - rx_data: status: %x\n", __func__, status); 433 len = (int)ks8842_read16(adapter, 17, REG_QMU_DATA_HI);
434 len &= 0xffff;
435 netdev_dbg(netdev, "%s - rx_data: status: %x\n",
436 __func__, status16);
437 } else {
438 status = ks8842_read32(adapter, 17, REG_QMU_DATA_LO);
439 len = (status >> 16) & 0x7ff;
440 status &= 0xffff;
441 netdev_dbg(netdev, "%s - rx_data: status: %x\n",
442 __func__, status);
443 }
372 444
373 /* check the status */ 445 /* check the status */
374 if ((status & RXSR_VALID) && !(status & RXSR_ERROR)) { 446 if ((status & RXSR_VALID) && !(status & RXSR_ERROR)) {
@@ -376,22 +448,32 @@ static void ks8842_rx_frame(struct net_device *netdev,
376 448
377 netdev_dbg(netdev, "%s, got package, len: %d\n", __func__, len); 449 netdev_dbg(netdev, "%s, got package, len: %d\n", __func__, len);
378 if (skb) { 450 if (skb) {
379 u32 *data;
380 451
381 netdev->stats.rx_packets++; 452 netdev->stats.rx_packets++;
382 netdev->stats.rx_bytes += len; 453 netdev->stats.rx_bytes += len;
383 if (status & RXSR_MULTICAST) 454 if (status & RXSR_MULTICAST)
384 netdev->stats.multicast++; 455 netdev->stats.multicast++;
385 456
386 data = (u32 *)skb_put(skb, len); 457 if (adapter->conf_flags & KS884X_16BIT) {
387 458 u16 *data16 = (u16 *)skb_put(skb, len);
388 ks8842_select_bank(adapter, 17); 459 ks8842_select_bank(adapter, 17);
389 while (len > 0) { 460 while (len > 0) {
390 *data++ = ioread32(adapter->hw_addr + 461 *data16++ = ioread16(adapter->hw_addr +
391 REG_QMU_DATA_LO); 462 REG_QMU_DATA_LO);
392 len -= sizeof(u32); 463 *data16++ = ioread16(adapter->hw_addr +
464 REG_QMU_DATA_HI);
465 len -= sizeof(u32);
466 }
467 } else {
468 u32 *data = (u32 *)skb_put(skb, len);
469
470 ks8842_select_bank(adapter, 17);
471 while (len > 0) {
472 *data++ = ioread32(adapter->hw_addr +
473 REG_QMU_DATA_LO);
474 len -= sizeof(u32);
475 }
393 } 476 }
394
395 skb->protocol = eth_type_trans(skb, netdev); 477 skb->protocol = eth_type_trans(skb, netdev);
396 netif_rx(skb); 478 netif_rx(skb);
397 } else 479 } else
@@ -669,6 +751,8 @@ static int __devinit ks8842_probe(struct platform_device *pdev)
669 adapter->netdev = netdev; 751 adapter->netdev = netdev;
670 INIT_WORK(&adapter->timeout_work, ks8842_tx_timeout_work); 752 INIT_WORK(&adapter->timeout_work, ks8842_tx_timeout_work);
671 adapter->hw_addr = ioremap(iomem->start, resource_size(iomem)); 753 adapter->hw_addr = ioremap(iomem->start, resource_size(iomem));
754 adapter->conf_flags = iomem->flags;
755
672 if (!adapter->hw_addr) 756 if (!adapter->hw_addr)
673 goto err_ioremap; 757 goto err_ioremap;
674 758