aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
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
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')
-rw-r--r--drivers/net/Kconfig7
-rw-r--r--drivers/net/ks8842.c174
2 files changed, 133 insertions, 48 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index f65857e88ec..88294762f9e 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1750,11 +1750,12 @@ config TLAN
1750 Please email feedback to <torben.mathiasen@compaq.com>. 1750 Please email feedback to <torben.mathiasen@compaq.com>.
1751 1751
1752config KS8842 1752config KS8842
1753 tristate "Micrel KSZ8842" 1753 tristate "Micrel KSZ8841/42 with generic bus interface"
1754 depends on HAS_IOMEM 1754 depends on HAS_IOMEM
1755 help 1755 help
1756 This platform driver is for Micrel KSZ8842 / KS8842 1756 This platform driver is for KSZ8841(1-port) / KS8842(2-port)
1757 2-port ethernet switch chip (managed, VLAN, QoS). 1757 ethernet switch chip (managed, VLAN, QoS) from Micrel or
1758 Timberdale(FPGA).
1758 1759
1759config KS8851 1760config KS8851
1760 tristate "Micrel KS8851 SPI" 1761 tristate "Micrel KS8851 SPI"
diff --git a/drivers/net/ks8842.c b/drivers/net/ks8842.c
index 0be92613acf..ee69dea69be 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