diff options
Diffstat (limited to 'drivers/net/bfin_mac.c')
-rw-r--r-- | drivers/net/bfin_mac.c | 264 |
1 files changed, 131 insertions, 133 deletions
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 9f971ed6b58d..c15fc281f79f 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c | |||
@@ -194,13 +194,13 @@ static int desc_list_init(void) | |||
194 | struct dma_descriptor *b = &(r->desc_b); | 194 | struct dma_descriptor *b = &(r->desc_b); |
195 | 195 | ||
196 | /* allocate a new skb for next time receive */ | 196 | /* allocate a new skb for next time receive */ |
197 | new_skb = dev_alloc_skb(PKT_BUF_SZ + 2); | 197 | new_skb = dev_alloc_skb(PKT_BUF_SZ + NET_IP_ALIGN); |
198 | if (!new_skb) { | 198 | if (!new_skb) { |
199 | printk(KERN_NOTICE DRV_NAME | 199 | printk(KERN_NOTICE DRV_NAME |
200 | ": init: low on mem - packet dropped\n"); | 200 | ": init: low on mem - packet dropped\n"); |
201 | goto init_error; | 201 | goto init_error; |
202 | } | 202 | } |
203 | skb_reserve(new_skb, 2); | 203 | skb_reserve(new_skb, NET_IP_ALIGN); |
204 | r->skb = new_skb; | 204 | r->skb = new_skb; |
205 | 205 | ||
206 | /* | 206 | /* |
@@ -566,9 +566,9 @@ static void adjust_tx_list(void) | |||
566 | */ | 566 | */ |
567 | if (current_tx_ptr->next->next == tx_list_head) { | 567 | if (current_tx_ptr->next->next == tx_list_head) { |
568 | while (tx_list_head->status.status_word == 0) { | 568 | while (tx_list_head->status.status_word == 0) { |
569 | mdelay(1); | 569 | udelay(10); |
570 | if (tx_list_head->status.status_word != 0 | 570 | if (tx_list_head->status.status_word != 0 |
571 | || !(bfin_read_DMA2_IRQ_STATUS() & 0x08)) { | 571 | || !(bfin_read_DMA2_IRQ_STATUS() & DMA_RUN)) { |
572 | goto adjust_head; | 572 | goto adjust_head; |
573 | } | 573 | } |
574 | if (timeout_cnt-- < 0) { | 574 | if (timeout_cnt-- < 0) { |
@@ -606,93 +606,41 @@ static int bfin_mac_hard_start_xmit(struct sk_buff *skb, | |||
606 | struct net_device *dev) | 606 | struct net_device *dev) |
607 | { | 607 | { |
608 | u16 *data; | 608 | u16 *data; |
609 | 609 | u32 data_align = (unsigned long)(skb->data) & 0x3; | |
610 | current_tx_ptr->skb = skb; | 610 | current_tx_ptr->skb = skb; |
611 | 611 | ||
612 | if (ANOMALY_05000285) { | 612 | if (data_align == 0x2) { |
613 | /* | 613 | /* move skb->data to current_tx_ptr payload */ |
614 | * TXDWA feature is not avaible to older revision < 0.3 silicon | 614 | data = (u16 *)(skb->data) - 1; |
615 | * of BF537 | 615 | *data = (u16)(skb->len); |
616 | * | 616 | current_tx_ptr->desc_a.start_addr = (u32)data; |
617 | * Only if data buffer is ODD WORD alignment, we do not | 617 | /* this is important! */ |
618 | * need to memcpy | 618 | blackfin_dcache_flush_range((u32)data, |
619 | */ | 619 | (u32)((u8 *)data + skb->len + 4)); |
620 | u32 data_align = (u32)(skb->data) & 0x3; | ||
621 | if (data_align == 0x2) { | ||
622 | /* move skb->data to current_tx_ptr payload */ | ||
623 | data = (u16 *)(skb->data) - 1; | ||
624 | *data = (u16)(skb->len); | ||
625 | current_tx_ptr->desc_a.start_addr = (u32)data; | ||
626 | /* this is important! */ | ||
627 | blackfin_dcache_flush_range((u32)data, | ||
628 | (u32)((u8 *)data + skb->len + 4)); | ||
629 | } else { | ||
630 | *((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len); | ||
631 | memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data, | ||
632 | skb->len); | ||
633 | current_tx_ptr->desc_a.start_addr = | ||
634 | (u32)current_tx_ptr->packet; | ||
635 | if (current_tx_ptr->status.status_word != 0) | ||
636 | current_tx_ptr->status.status_word = 0; | ||
637 | blackfin_dcache_flush_range( | ||
638 | (u32)current_tx_ptr->packet, | ||
639 | (u32)(current_tx_ptr->packet + skb->len + 2)); | ||
640 | } | ||
641 | } else { | 620 | } else { |
642 | /* | 621 | *((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len); |
643 | * TXDWA feature is avaible to revision < 0.3 silicon of | 622 | memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data, |
644 | * BF537 and always avaible to BF52x | 623 | skb->len); |
645 | */ | 624 | current_tx_ptr->desc_a.start_addr = |
646 | u32 data_align = (u32)(skb->data) & 0x3; | 625 | (u32)current_tx_ptr->packet; |
647 | if (data_align == 0x0) { | 626 | if (current_tx_ptr->status.status_word != 0) |
648 | u16 sysctl = bfin_read_EMAC_SYSCTL(); | 627 | current_tx_ptr->status.status_word = 0; |
649 | sysctl |= TXDWA; | 628 | blackfin_dcache_flush_range( |
650 | bfin_write_EMAC_SYSCTL(sysctl); | 629 | (u32)current_tx_ptr->packet, |
651 | 630 | (u32)(current_tx_ptr->packet + skb->len + 2)); | |
652 | /* move skb->data to current_tx_ptr payload */ | ||
653 | data = (u16 *)(skb->data) - 2; | ||
654 | *data = (u16)(skb->len); | ||
655 | current_tx_ptr->desc_a.start_addr = (u32)data; | ||
656 | /* this is important! */ | ||
657 | blackfin_dcache_flush_range( | ||
658 | (u32)data, | ||
659 | (u32)((u8 *)data + skb->len + 4)); | ||
660 | } else if (data_align == 0x2) { | ||
661 | u16 sysctl = bfin_read_EMAC_SYSCTL(); | ||
662 | sysctl &= ~TXDWA; | ||
663 | bfin_write_EMAC_SYSCTL(sysctl); | ||
664 | |||
665 | /* move skb->data to current_tx_ptr payload */ | ||
666 | data = (u16 *)(skb->data) - 1; | ||
667 | *data = (u16)(skb->len); | ||
668 | current_tx_ptr->desc_a.start_addr = (u32)data; | ||
669 | /* this is important! */ | ||
670 | blackfin_dcache_flush_range( | ||
671 | (u32)data, | ||
672 | (u32)((u8 *)data + skb->len + 4)); | ||
673 | } else { | ||
674 | u16 sysctl = bfin_read_EMAC_SYSCTL(); | ||
675 | sysctl &= ~TXDWA; | ||
676 | bfin_write_EMAC_SYSCTL(sysctl); | ||
677 | |||
678 | *((u16 *)(current_tx_ptr->packet)) = (u16)(skb->len); | ||
679 | memcpy((u8 *)(current_tx_ptr->packet + 2), skb->data, | ||
680 | skb->len); | ||
681 | current_tx_ptr->desc_a.start_addr = | ||
682 | (u32)current_tx_ptr->packet; | ||
683 | if (current_tx_ptr->status.status_word != 0) | ||
684 | current_tx_ptr->status.status_word = 0; | ||
685 | blackfin_dcache_flush_range( | ||
686 | (u32)current_tx_ptr->packet, | ||
687 | (u32)(current_tx_ptr->packet + skb->len + 2)); | ||
688 | } | ||
689 | } | 631 | } |
690 | 632 | ||
633 | /* make sure the internal data buffers in the core are drained | ||
634 | * so that the DMA descriptors are completely written when the | ||
635 | * DMA engine goes to fetch them below | ||
636 | */ | ||
637 | SSYNC(); | ||
638 | |||
691 | /* enable this packet's dma */ | 639 | /* enable this packet's dma */ |
692 | current_tx_ptr->desc_a.config |= DMAEN; | 640 | current_tx_ptr->desc_a.config |= DMAEN; |
693 | 641 | ||
694 | /* tx dma is running, just return */ | 642 | /* tx dma is running, just return */ |
695 | if (bfin_read_DMA2_IRQ_STATUS() & 0x08) | 643 | if (bfin_read_DMA2_IRQ_STATUS() & DMA_RUN) |
696 | goto out; | 644 | goto out; |
697 | 645 | ||
698 | /* tx dma is not running */ | 646 | /* tx dma is not running */ |
@@ -718,7 +666,7 @@ static void bfin_mac_rx(struct net_device *dev) | |||
718 | 666 | ||
719 | /* allocate a new skb for next time receive */ | 667 | /* allocate a new skb for next time receive */ |
720 | skb = current_rx_ptr->skb; | 668 | skb = current_rx_ptr->skb; |
721 | new_skb = dev_alloc_skb(PKT_BUF_SZ + 2); | 669 | new_skb = dev_alloc_skb(PKT_BUF_SZ + NET_IP_ALIGN); |
722 | if (!new_skb) { | 670 | if (!new_skb) { |
723 | printk(KERN_NOTICE DRV_NAME | 671 | printk(KERN_NOTICE DRV_NAME |
724 | ": rx: low on mem - packet dropped\n"); | 672 | ": rx: low on mem - packet dropped\n"); |
@@ -726,7 +674,7 @@ static void bfin_mac_rx(struct net_device *dev) | |||
726 | goto out; | 674 | goto out; |
727 | } | 675 | } |
728 | /* reserve 2 bytes for RXDWA padding */ | 676 | /* reserve 2 bytes for RXDWA padding */ |
729 | skb_reserve(new_skb, 2); | 677 | skb_reserve(new_skb, NET_IP_ALIGN); |
730 | current_rx_ptr->skb = new_skb; | 678 | current_rx_ptr->skb = new_skb; |
731 | current_rx_ptr->desc_a.start_addr = (unsigned long)new_skb->data - 2; | 679 | current_rx_ptr->desc_a.start_addr = (unsigned long)new_skb->data - 2; |
732 | 680 | ||
@@ -979,22 +927,7 @@ static int bfin_mac_open(struct net_device *dev) | |||
979 | return 0; | 927 | return 0; |
980 | } | 928 | } |
981 | 929 | ||
982 | static const struct net_device_ops bfin_mac_netdev_ops = { | ||
983 | .ndo_open = bfin_mac_open, | ||
984 | .ndo_stop = bfin_mac_close, | ||
985 | .ndo_start_xmit = bfin_mac_hard_start_xmit, | ||
986 | .ndo_set_mac_address = bfin_mac_set_mac_address, | ||
987 | .ndo_tx_timeout = bfin_mac_timeout, | ||
988 | .ndo_set_multicast_list = bfin_mac_set_multicast_list, | ||
989 | .ndo_validate_addr = eth_validate_addr, | ||
990 | .ndo_change_mtu = eth_change_mtu, | ||
991 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
992 | .ndo_poll_controller = bfin_mac_poll, | ||
993 | #endif | ||
994 | }; | ||
995 | |||
996 | /* | 930 | /* |
997 | * | ||
998 | * this makes the board clean up everything that it can | 931 | * this makes the board clean up everything that it can |
999 | * and not talk to the outside world. Caused by | 932 | * and not talk to the outside world. Caused by |
1000 | * an 'ifconfig ethX down' | 933 | * an 'ifconfig ethX down' |
@@ -1019,11 +952,26 @@ static int bfin_mac_close(struct net_device *dev) | |||
1019 | return 0; | 952 | return 0; |
1020 | } | 953 | } |
1021 | 954 | ||
955 | static const struct net_device_ops bfin_mac_netdev_ops = { | ||
956 | .ndo_open = bfin_mac_open, | ||
957 | .ndo_stop = bfin_mac_close, | ||
958 | .ndo_start_xmit = bfin_mac_hard_start_xmit, | ||
959 | .ndo_set_mac_address = bfin_mac_set_mac_address, | ||
960 | .ndo_tx_timeout = bfin_mac_timeout, | ||
961 | .ndo_set_multicast_list = bfin_mac_set_multicast_list, | ||
962 | .ndo_validate_addr = eth_validate_addr, | ||
963 | .ndo_change_mtu = eth_change_mtu, | ||
964 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
965 | .ndo_poll_controller = bfin_mac_poll, | ||
966 | #endif | ||
967 | }; | ||
968 | |||
1022 | static int __devinit bfin_mac_probe(struct platform_device *pdev) | 969 | static int __devinit bfin_mac_probe(struct platform_device *pdev) |
1023 | { | 970 | { |
1024 | struct net_device *ndev; | 971 | struct net_device *ndev; |
1025 | struct bfin_mac_local *lp; | 972 | struct bfin_mac_local *lp; |
1026 | int rc, i; | 973 | struct platform_device *pd; |
974 | int rc; | ||
1027 | 975 | ||
1028 | ndev = alloc_etherdev(sizeof(struct bfin_mac_local)); | 976 | ndev = alloc_etherdev(sizeof(struct bfin_mac_local)); |
1029 | if (!ndev) { | 977 | if (!ndev) { |
@@ -1048,13 +996,6 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev) | |||
1048 | goto out_err_probe_mac; | 996 | goto out_err_probe_mac; |
1049 | } | 997 | } |
1050 | 998 | ||
1051 | /* set the GPIO pins to Ethernet mode */ | ||
1052 | rc = peripheral_request_list(pin_req, DRV_NAME); | ||
1053 | if (rc) { | ||
1054 | dev_err(&pdev->dev, "Requesting peripherals failed!\n"); | ||
1055 | rc = -EFAULT; | ||
1056 | goto out_err_setup_pin_mux; | ||
1057 | } | ||
1058 | 999 | ||
1059 | /* | 1000 | /* |
1060 | * Is it valid? (Did bootloader initialize it?) | 1001 | * Is it valid? (Did bootloader initialize it?) |
@@ -1070,26 +1011,14 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev) | |||
1070 | 1011 | ||
1071 | setup_mac_addr(ndev->dev_addr); | 1012 | setup_mac_addr(ndev->dev_addr); |
1072 | 1013 | ||
1073 | /* MDIO bus initial */ | 1014 | if (!pdev->dev.platform_data) { |
1074 | lp->mii_bus = mdiobus_alloc(); | 1015 | dev_err(&pdev->dev, "Cannot get platform device bfin_mii_bus!\n"); |
1075 | if (lp->mii_bus == NULL) | 1016 | rc = -ENODEV; |
1076 | goto out_err_mdiobus_alloc; | 1017 | goto out_err_probe_mac; |
1077 | |||
1078 | lp->mii_bus->priv = ndev; | ||
1079 | lp->mii_bus->read = bfin_mdiobus_read; | ||
1080 | lp->mii_bus->write = bfin_mdiobus_write; | ||
1081 | lp->mii_bus->reset = bfin_mdiobus_reset; | ||
1082 | lp->mii_bus->name = "bfin_mac_mdio"; | ||
1083 | snprintf(lp->mii_bus->id, MII_BUS_ID_SIZE, "0"); | ||
1084 | lp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); | ||
1085 | for (i = 0; i < PHY_MAX_ADDR; ++i) | ||
1086 | lp->mii_bus->irq[i] = PHY_POLL; | ||
1087 | |||
1088 | rc = mdiobus_register(lp->mii_bus); | ||
1089 | if (rc) { | ||
1090 | dev_err(&pdev->dev, "Cannot register MDIO bus!\n"); | ||
1091 | goto out_err_mdiobus_register; | ||
1092 | } | 1018 | } |
1019 | pd = pdev->dev.platform_data; | ||
1020 | lp->mii_bus = platform_get_drvdata(pd); | ||
1021 | lp->mii_bus->priv = ndev; | ||
1093 | 1022 | ||
1094 | rc = mii_probe(ndev); | 1023 | rc = mii_probe(ndev); |
1095 | if (rc) { | 1024 | if (rc) { |
@@ -1108,7 +1037,7 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev) | |||
1108 | /* now, enable interrupts */ | 1037 | /* now, enable interrupts */ |
1109 | /* register irq handler */ | 1038 | /* register irq handler */ |
1110 | rc = request_irq(IRQ_MAC_RX, bfin_mac_interrupt, | 1039 | rc = request_irq(IRQ_MAC_RX, bfin_mac_interrupt, |
1111 | IRQF_DISABLED | IRQF_SHARED, "EMAC_RX", ndev); | 1040 | IRQF_DISABLED, "EMAC_RX", ndev); |
1112 | if (rc) { | 1041 | if (rc) { |
1113 | dev_err(&pdev->dev, "Cannot request Blackfin MAC RX IRQ!\n"); | 1042 | dev_err(&pdev->dev, "Cannot request Blackfin MAC RX IRQ!\n"); |
1114 | rc = -EBUSY; | 1043 | rc = -EBUSY; |
@@ -1131,11 +1060,8 @@ out_err_reg_ndev: | |||
1131 | out_err_request_irq: | 1060 | out_err_request_irq: |
1132 | out_err_mii_probe: | 1061 | out_err_mii_probe: |
1133 | mdiobus_unregister(lp->mii_bus); | 1062 | mdiobus_unregister(lp->mii_bus); |
1134 | out_err_mdiobus_register: | ||
1135 | mdiobus_free(lp->mii_bus); | 1063 | mdiobus_free(lp->mii_bus); |
1136 | out_err_mdiobus_alloc: | ||
1137 | peripheral_free_list(pin_req); | 1064 | peripheral_free_list(pin_req); |
1138 | out_err_setup_pin_mux: | ||
1139 | out_err_probe_mac: | 1065 | out_err_probe_mac: |
1140 | platform_set_drvdata(pdev, NULL); | 1066 | platform_set_drvdata(pdev, NULL); |
1141 | free_netdev(ndev); | 1067 | free_netdev(ndev); |
@@ -1150,8 +1076,7 @@ static int __devexit bfin_mac_remove(struct platform_device *pdev) | |||
1150 | 1076 | ||
1151 | platform_set_drvdata(pdev, NULL); | 1077 | platform_set_drvdata(pdev, NULL); |
1152 | 1078 | ||
1153 | mdiobus_unregister(lp->mii_bus); | 1079 | lp->mii_bus->priv = NULL; |
1154 | mdiobus_free(lp->mii_bus); | ||
1155 | 1080 | ||
1156 | unregister_netdev(ndev); | 1081 | unregister_netdev(ndev); |
1157 | 1082 | ||
@@ -1189,6 +1114,74 @@ static int bfin_mac_resume(struct platform_device *pdev) | |||
1189 | #define bfin_mac_resume NULL | 1114 | #define bfin_mac_resume NULL |
1190 | #endif /* CONFIG_PM */ | 1115 | #endif /* CONFIG_PM */ |
1191 | 1116 | ||
1117 | static int __devinit bfin_mii_bus_probe(struct platform_device *pdev) | ||
1118 | { | ||
1119 | struct mii_bus *miibus; | ||
1120 | int rc, i; | ||
1121 | |||
1122 | /* | ||
1123 | * We are setting up a network card, | ||
1124 | * so set the GPIO pins to Ethernet mode | ||
1125 | */ | ||
1126 | rc = peripheral_request_list(pin_req, DRV_NAME); | ||
1127 | if (rc) { | ||
1128 | dev_err(&pdev->dev, "Requesting peripherals failed!\n"); | ||
1129 | return rc; | ||
1130 | } | ||
1131 | |||
1132 | rc = -ENOMEM; | ||
1133 | miibus = mdiobus_alloc(); | ||
1134 | if (miibus == NULL) | ||
1135 | goto out_err_alloc; | ||
1136 | miibus->read = bfin_mdiobus_read; | ||
1137 | miibus->write = bfin_mdiobus_write; | ||
1138 | miibus->reset = bfin_mdiobus_reset; | ||
1139 | |||
1140 | miibus->parent = &pdev->dev; | ||
1141 | miibus->name = "bfin_mii_bus"; | ||
1142 | snprintf(miibus->id, MII_BUS_ID_SIZE, "0"); | ||
1143 | miibus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); | ||
1144 | if (miibus->irq == NULL) | ||
1145 | goto out_err_alloc; | ||
1146 | for (i = 0; i < PHY_MAX_ADDR; ++i) | ||
1147 | miibus->irq[i] = PHY_POLL; | ||
1148 | |||
1149 | rc = mdiobus_register(miibus); | ||
1150 | if (rc) { | ||
1151 | dev_err(&pdev->dev, "Cannot register MDIO bus!\n"); | ||
1152 | goto out_err_mdiobus_register; | ||
1153 | } | ||
1154 | |||
1155 | platform_set_drvdata(pdev, miibus); | ||
1156 | return 0; | ||
1157 | |||
1158 | out_err_mdiobus_register: | ||
1159 | mdiobus_free(miibus); | ||
1160 | out_err_alloc: | ||
1161 | peripheral_free_list(pin_req); | ||
1162 | |||
1163 | return rc; | ||
1164 | } | ||
1165 | |||
1166 | static int __devexit bfin_mii_bus_remove(struct platform_device *pdev) | ||
1167 | { | ||
1168 | struct mii_bus *miibus = platform_get_drvdata(pdev); | ||
1169 | platform_set_drvdata(pdev, NULL); | ||
1170 | mdiobus_unregister(miibus); | ||
1171 | mdiobus_free(miibus); | ||
1172 | peripheral_free_list(pin_req); | ||
1173 | return 0; | ||
1174 | } | ||
1175 | |||
1176 | static struct platform_driver bfin_mii_bus_driver = { | ||
1177 | .probe = bfin_mii_bus_probe, | ||
1178 | .remove = __devexit_p(bfin_mii_bus_remove), | ||
1179 | .driver = { | ||
1180 | .name = "bfin_mii_bus", | ||
1181 | .owner = THIS_MODULE, | ||
1182 | }, | ||
1183 | }; | ||
1184 | |||
1192 | static struct platform_driver bfin_mac_driver = { | 1185 | static struct platform_driver bfin_mac_driver = { |
1193 | .probe = bfin_mac_probe, | 1186 | .probe = bfin_mac_probe, |
1194 | .remove = __devexit_p(bfin_mac_remove), | 1187 | .remove = __devexit_p(bfin_mac_remove), |
@@ -1202,7 +1195,11 @@ static struct platform_driver bfin_mac_driver = { | |||
1202 | 1195 | ||
1203 | static int __init bfin_mac_init(void) | 1196 | static int __init bfin_mac_init(void) |
1204 | { | 1197 | { |
1205 | return platform_driver_register(&bfin_mac_driver); | 1198 | int ret; |
1199 | ret = platform_driver_register(&bfin_mii_bus_driver); | ||
1200 | if (!ret) | ||
1201 | return platform_driver_register(&bfin_mac_driver); | ||
1202 | return -ENODEV; | ||
1206 | } | 1203 | } |
1207 | 1204 | ||
1208 | module_init(bfin_mac_init); | 1205 | module_init(bfin_mac_init); |
@@ -1210,6 +1207,7 @@ module_init(bfin_mac_init); | |||
1210 | static void __exit bfin_mac_cleanup(void) | 1207 | static void __exit bfin_mac_cleanup(void) |
1211 | { | 1208 | { |
1212 | platform_driver_unregister(&bfin_mac_driver); | 1209 | platform_driver_unregister(&bfin_mac_driver); |
1210 | platform_driver_unregister(&bfin_mii_bus_driver); | ||
1213 | } | 1211 | } |
1214 | 1212 | ||
1215 | module_exit(bfin_mac_cleanup); | 1213 | module_exit(bfin_mac_cleanup); |