diff options
Diffstat (limited to 'drivers/net/arm/ks8695net.c')
-rw-r--r-- | drivers/net/arm/ks8695net.c | 291 |
1 files changed, 97 insertions, 194 deletions
diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c index 54c6d849cf25..a7b0caa18179 100644 --- a/drivers/net/arm/ks8695net.c +++ b/drivers/net/arm/ks8695net.c | |||
@@ -854,12 +854,12 @@ ks8695_set_msglevel(struct net_device *ndev, u32 value) | |||
854 | } | 854 | } |
855 | 855 | ||
856 | /** | 856 | /** |
857 | * ks8695_get_settings - Get device-specific settings. | 857 | * ks8695_wan_get_settings - Get device-specific settings. |
858 | * @ndev: The network device to read settings from | 858 | * @ndev: The network device to read settings from |
859 | * @cmd: The ethtool structure to read into | 859 | * @cmd: The ethtool structure to read into |
860 | */ | 860 | */ |
861 | static int | 861 | static int |
862 | ks8695_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd) | 862 | ks8695_wan_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd) |
863 | { | 863 | { |
864 | struct ks8695_priv *ksp = netdev_priv(ndev); | 864 | struct ks8695_priv *ksp = netdev_priv(ndev); |
865 | u32 ctrl; | 865 | u32 ctrl; |
@@ -870,69 +870,51 @@ ks8695_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd) | |||
870 | SUPPORTED_TP | SUPPORTED_MII); | 870 | SUPPORTED_TP | SUPPORTED_MII); |
871 | cmd->transceiver = XCVR_INTERNAL; | 871 | cmd->transceiver = XCVR_INTERNAL; |
872 | 872 | ||
873 | /* Port specific extras */ | 873 | cmd->advertising = ADVERTISED_TP | ADVERTISED_MII; |
874 | switch (ksp->dtype) { | 874 | cmd->port = PORT_MII; |
875 | case KS8695_DTYPE_HPNA: | 875 | cmd->supported |= (SUPPORTED_Autoneg | SUPPORTED_Pause); |
876 | cmd->phy_address = 0; | 876 | cmd->phy_address = 0; |
877 | /* not supported for HPNA */ | ||
878 | cmd->autoneg = AUTONEG_DISABLE; | ||
879 | 877 | ||
880 | /* BUG: Erm, dtype hpna implies no phy regs */ | 878 | ctrl = readl(ksp->phyiface_regs + KS8695_WMC); |
881 | /* | 879 | if ((ctrl & WMC_WAND) == 0) { |
882 | ctrl = readl(KS8695_MISC_VA + KS8695_HMC); | 880 | /* auto-negotiation is enabled */ |
883 | cmd->speed = (ctrl & HMC_HSS) ? SPEED_100 : SPEED_10; | 881 | cmd->advertising |= ADVERTISED_Autoneg; |
884 | cmd->duplex = (ctrl & HMC_HDS) ? DUPLEX_FULL : DUPLEX_HALF; | 882 | if (ctrl & WMC_WANA100F) |
885 | */ | 883 | cmd->advertising |= ADVERTISED_100baseT_Full; |
886 | return -EOPNOTSUPP; | 884 | if (ctrl & WMC_WANA100H) |
887 | case KS8695_DTYPE_WAN: | 885 | cmd->advertising |= ADVERTISED_100baseT_Half; |
888 | cmd->advertising = ADVERTISED_TP | ADVERTISED_MII; | 886 | if (ctrl & WMC_WANA10F) |
889 | cmd->port = PORT_MII; | 887 | cmd->advertising |= ADVERTISED_10baseT_Full; |
890 | cmd->supported |= (SUPPORTED_Autoneg | SUPPORTED_Pause); | 888 | if (ctrl & WMC_WANA10H) |
891 | cmd->phy_address = 0; | 889 | cmd->advertising |= ADVERTISED_10baseT_Half; |
890 | if (ctrl & WMC_WANAP) | ||
891 | cmd->advertising |= ADVERTISED_Pause; | ||
892 | cmd->autoneg = AUTONEG_ENABLE; | ||
893 | |||
894 | ethtool_cmd_speed_set(cmd, | ||
895 | (ctrl & WMC_WSS) ? SPEED_100 : SPEED_10); | ||
896 | cmd->duplex = (ctrl & WMC_WDS) ? | ||
897 | DUPLEX_FULL : DUPLEX_HALF; | ||
898 | } else { | ||
899 | /* auto-negotiation is disabled */ | ||
900 | cmd->autoneg = AUTONEG_DISABLE; | ||
892 | 901 | ||
893 | ctrl = readl(ksp->phyiface_regs + KS8695_WMC); | 902 | ethtool_cmd_speed_set(cmd, ((ctrl & WMC_WANF100) ? |
894 | if ((ctrl & WMC_WAND) == 0) { | 903 | SPEED_100 : SPEED_10)); |
895 | /* auto-negotiation is enabled */ | 904 | cmd->duplex = (ctrl & WMC_WANFF) ? |
896 | cmd->advertising |= ADVERTISED_Autoneg; | 905 | DUPLEX_FULL : DUPLEX_HALF; |
897 | if (ctrl & WMC_WANA100F) | ||
898 | cmd->advertising |= ADVERTISED_100baseT_Full; | ||
899 | if (ctrl & WMC_WANA100H) | ||
900 | cmd->advertising |= ADVERTISED_100baseT_Half; | ||
901 | if (ctrl & WMC_WANA10F) | ||
902 | cmd->advertising |= ADVERTISED_10baseT_Full; | ||
903 | if (ctrl & WMC_WANA10H) | ||
904 | cmd->advertising |= ADVERTISED_10baseT_Half; | ||
905 | if (ctrl & WMC_WANAP) | ||
906 | cmd->advertising |= ADVERTISED_Pause; | ||
907 | cmd->autoneg = AUTONEG_ENABLE; | ||
908 | |||
909 | cmd->speed = (ctrl & WMC_WSS) ? SPEED_100 : SPEED_10; | ||
910 | cmd->duplex = (ctrl & WMC_WDS) ? | ||
911 | DUPLEX_FULL : DUPLEX_HALF; | ||
912 | } else { | ||
913 | /* auto-negotiation is disabled */ | ||
914 | cmd->autoneg = AUTONEG_DISABLE; | ||
915 | |||
916 | cmd->speed = (ctrl & WMC_WANF100) ? | ||
917 | SPEED_100 : SPEED_10; | ||
918 | cmd->duplex = (ctrl & WMC_WANFF) ? | ||
919 | DUPLEX_FULL : DUPLEX_HALF; | ||
920 | } | ||
921 | break; | ||
922 | case KS8695_DTYPE_LAN: | ||
923 | return -EOPNOTSUPP; | ||
924 | } | 906 | } |
925 | 907 | ||
926 | return 0; | 908 | return 0; |
927 | } | 909 | } |
928 | 910 | ||
929 | /** | 911 | /** |
930 | * ks8695_set_settings - Set device-specific settings. | 912 | * ks8695_wan_set_settings - Set device-specific settings. |
931 | * @ndev: The network device to configure | 913 | * @ndev: The network device to configure |
932 | * @cmd: The settings to configure | 914 | * @cmd: The settings to configure |
933 | */ | 915 | */ |
934 | static int | 916 | static int |
935 | ks8695_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd) | 917 | ks8695_wan_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd) |
936 | { | 918 | { |
937 | struct ks8695_priv *ksp = netdev_priv(ndev); | 919 | struct ks8695_priv *ksp = netdev_priv(ndev); |
938 | u32 ctrl; | 920 | u32 ctrl; |
@@ -956,171 +938,85 @@ ks8695_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd) | |||
956 | ADVERTISED_100baseT_Full)) == 0) | 938 | ADVERTISED_100baseT_Full)) == 0) |
957 | return -EINVAL; | 939 | return -EINVAL; |
958 | 940 | ||
959 | switch (ksp->dtype) { | 941 | ctrl = readl(ksp->phyiface_regs + KS8695_WMC); |
960 | case KS8695_DTYPE_HPNA: | ||
961 | /* HPNA does not support auto-negotiation. */ | ||
962 | return -EINVAL; | ||
963 | case KS8695_DTYPE_WAN: | ||
964 | ctrl = readl(ksp->phyiface_regs + KS8695_WMC); | ||
965 | |||
966 | ctrl &= ~(WMC_WAND | WMC_WANA100F | WMC_WANA100H | | ||
967 | WMC_WANA10F | WMC_WANA10H); | ||
968 | if (cmd->advertising & ADVERTISED_100baseT_Full) | ||
969 | ctrl |= WMC_WANA100F; | ||
970 | if (cmd->advertising & ADVERTISED_100baseT_Half) | ||
971 | ctrl |= WMC_WANA100H; | ||
972 | if (cmd->advertising & ADVERTISED_10baseT_Full) | ||
973 | ctrl |= WMC_WANA10F; | ||
974 | if (cmd->advertising & ADVERTISED_10baseT_Half) | ||
975 | ctrl |= WMC_WANA10H; | ||
976 | |||
977 | /* force a re-negotiation */ | ||
978 | ctrl |= WMC_WANR; | ||
979 | writel(ctrl, ksp->phyiface_regs + KS8695_WMC); | ||
980 | break; | ||
981 | case KS8695_DTYPE_LAN: | ||
982 | return -EOPNOTSUPP; | ||
983 | } | ||
984 | 942 | ||
943 | ctrl &= ~(WMC_WAND | WMC_WANA100F | WMC_WANA100H | | ||
944 | WMC_WANA10F | WMC_WANA10H); | ||
945 | if (cmd->advertising & ADVERTISED_100baseT_Full) | ||
946 | ctrl |= WMC_WANA100F; | ||
947 | if (cmd->advertising & ADVERTISED_100baseT_Half) | ||
948 | ctrl |= WMC_WANA100H; | ||
949 | if (cmd->advertising & ADVERTISED_10baseT_Full) | ||
950 | ctrl |= WMC_WANA10F; | ||
951 | if (cmd->advertising & ADVERTISED_10baseT_Half) | ||
952 | ctrl |= WMC_WANA10H; | ||
953 | |||
954 | /* force a re-negotiation */ | ||
955 | ctrl |= WMC_WANR; | ||
956 | writel(ctrl, ksp->phyiface_regs + KS8695_WMC); | ||
985 | } else { | 957 | } else { |
986 | switch (ksp->dtype) { | 958 | ctrl = readl(ksp->phyiface_regs + KS8695_WMC); |
987 | case KS8695_DTYPE_HPNA: | 959 | |
988 | /* BUG: dtype_hpna implies no phy registers */ | 960 | /* disable auto-negotiation */ |
989 | /* | 961 | ctrl |= WMC_WAND; |
990 | ctrl = __raw_readl(KS8695_MISC_VA + KS8695_HMC); | 962 | ctrl &= ~(WMC_WANF100 | WMC_WANFF); |
991 | 963 | ||
992 | ctrl &= ~(HMC_HSS | HMC_HDS); | 964 | if (cmd->speed == SPEED_100) |
993 | if (cmd->speed == SPEED_100) | 965 | ctrl |= WMC_WANF100; |
994 | ctrl |= HMC_HSS; | 966 | if (cmd->duplex == DUPLEX_FULL) |
995 | if (cmd->duplex == DUPLEX_FULL) | 967 | ctrl |= WMC_WANFF; |
996 | ctrl |= HMC_HDS; | 968 | |
997 | 969 | writel(ctrl, ksp->phyiface_regs + KS8695_WMC); | |
998 | __raw_writel(ctrl, KS8695_MISC_VA + KS8695_HMC); | ||
999 | */ | ||
1000 | return -EOPNOTSUPP; | ||
1001 | case KS8695_DTYPE_WAN: | ||
1002 | ctrl = readl(ksp->phyiface_regs + KS8695_WMC); | ||
1003 | |||
1004 | /* disable auto-negotiation */ | ||
1005 | ctrl |= WMC_WAND; | ||
1006 | ctrl &= ~(WMC_WANF100 | WMC_WANFF); | ||
1007 | |||
1008 | if (cmd->speed == SPEED_100) | ||
1009 | ctrl |= WMC_WANF100; | ||
1010 | if (cmd->duplex == DUPLEX_FULL) | ||
1011 | ctrl |= WMC_WANFF; | ||
1012 | |||
1013 | writel(ctrl, ksp->phyiface_regs + KS8695_WMC); | ||
1014 | break; | ||
1015 | case KS8695_DTYPE_LAN: | ||
1016 | return -EOPNOTSUPP; | ||
1017 | } | ||
1018 | } | 970 | } |
1019 | 971 | ||
1020 | return 0; | 972 | return 0; |
1021 | } | 973 | } |
1022 | 974 | ||
1023 | /** | 975 | /** |
1024 | * ks8695_nwayreset - Restart the autonegotiation on the port. | 976 | * ks8695_wan_nwayreset - Restart the autonegotiation on the port. |
1025 | * @ndev: The network device to restart autoneotiation on | 977 | * @ndev: The network device to restart autoneotiation on |
1026 | */ | 978 | */ |
1027 | static int | 979 | static int |
1028 | ks8695_nwayreset(struct net_device *ndev) | 980 | ks8695_wan_nwayreset(struct net_device *ndev) |
1029 | { | 981 | { |
1030 | struct ks8695_priv *ksp = netdev_priv(ndev); | 982 | struct ks8695_priv *ksp = netdev_priv(ndev); |
1031 | u32 ctrl; | 983 | u32 ctrl; |
1032 | 984 | ||
1033 | switch (ksp->dtype) { | 985 | ctrl = readl(ksp->phyiface_regs + KS8695_WMC); |
1034 | case KS8695_DTYPE_HPNA: | ||
1035 | /* No phy means no autonegotiation on hpna */ | ||
1036 | return -EINVAL; | ||
1037 | case KS8695_DTYPE_WAN: | ||
1038 | ctrl = readl(ksp->phyiface_regs + KS8695_WMC); | ||
1039 | |||
1040 | if ((ctrl & WMC_WAND) == 0) | ||
1041 | writel(ctrl | WMC_WANR, | ||
1042 | ksp->phyiface_regs + KS8695_WMC); | ||
1043 | else | ||
1044 | /* auto-negotiation not enabled */ | ||
1045 | return -EINVAL; | ||
1046 | break; | ||
1047 | case KS8695_DTYPE_LAN: | ||
1048 | return -EOPNOTSUPP; | ||
1049 | } | ||
1050 | |||
1051 | return 0; | ||
1052 | } | ||
1053 | 986 | ||
1054 | /** | 987 | if ((ctrl & WMC_WAND) == 0) |
1055 | * ks8695_get_link - Retrieve link status of network interface | 988 | writel(ctrl | WMC_WANR, |
1056 | * @ndev: The network interface to retrive the link status of. | 989 | ksp->phyiface_regs + KS8695_WMC); |
1057 | */ | 990 | else |
1058 | static u32 | 991 | /* auto-negotiation not enabled */ |
1059 | ks8695_get_link(struct net_device *ndev) | 992 | return -EINVAL; |
1060 | { | ||
1061 | struct ks8695_priv *ksp = netdev_priv(ndev); | ||
1062 | u32 ctrl; | ||
1063 | 993 | ||
1064 | switch (ksp->dtype) { | ||
1065 | case KS8695_DTYPE_HPNA: | ||
1066 | /* HPNA always has link */ | ||
1067 | return 1; | ||
1068 | case KS8695_DTYPE_WAN: | ||
1069 | /* WAN we can read the PHY for */ | ||
1070 | ctrl = readl(ksp->phyiface_regs + KS8695_WMC); | ||
1071 | return ctrl & WMC_WLS; | ||
1072 | case KS8695_DTYPE_LAN: | ||
1073 | return -EOPNOTSUPP; | ||
1074 | } | ||
1075 | return 0; | 994 | return 0; |
1076 | } | 995 | } |
1077 | 996 | ||
1078 | /** | 997 | /** |
1079 | * ks8695_get_pause - Retrieve network pause/flow-control advertising | 998 | * ks8695_wan_get_pause - Retrieve network pause/flow-control advertising |
1080 | * @ndev: The device to retrieve settings from | 999 | * @ndev: The device to retrieve settings from |
1081 | * @param: The structure to fill out with the information | 1000 | * @param: The structure to fill out with the information |
1082 | */ | 1001 | */ |
1083 | static void | 1002 | static void |
1084 | ks8695_get_pause(struct net_device *ndev, struct ethtool_pauseparam *param) | 1003 | ks8695_wan_get_pause(struct net_device *ndev, struct ethtool_pauseparam *param) |
1085 | { | 1004 | { |
1086 | struct ks8695_priv *ksp = netdev_priv(ndev); | 1005 | struct ks8695_priv *ksp = netdev_priv(ndev); |
1087 | u32 ctrl; | 1006 | u32 ctrl; |
1088 | 1007 | ||
1089 | switch (ksp->dtype) { | 1008 | ctrl = readl(ksp->phyiface_regs + KS8695_WMC); |
1090 | case KS8695_DTYPE_HPNA: | ||
1091 | /* No phy link on hpna to configure */ | ||
1092 | return; | ||
1093 | case KS8695_DTYPE_WAN: | ||
1094 | ctrl = readl(ksp->phyiface_regs + KS8695_WMC); | ||
1095 | |||
1096 | /* advertise Pause */ | ||
1097 | param->autoneg = (ctrl & WMC_WANAP); | ||
1098 | 1009 | ||
1099 | /* current Rx Flow-control */ | 1010 | /* advertise Pause */ |
1100 | ctrl = ks8695_readreg(ksp, KS8695_DRXC); | 1011 | param->autoneg = (ctrl & WMC_WANAP); |
1101 | param->rx_pause = (ctrl & DRXC_RFCE); | ||
1102 | 1012 | ||
1103 | /* current Tx Flow-control */ | 1013 | /* current Rx Flow-control */ |
1104 | ctrl = ks8695_readreg(ksp, KS8695_DTXC); | 1014 | ctrl = ks8695_readreg(ksp, KS8695_DRXC); |
1105 | param->tx_pause = (ctrl & DTXC_TFCE); | 1015 | param->rx_pause = (ctrl & DRXC_RFCE); |
1106 | break; | ||
1107 | case KS8695_DTYPE_LAN: | ||
1108 | /* The LAN's "phy" is a direct-attached switch */ | ||
1109 | return; | ||
1110 | } | ||
1111 | } | ||
1112 | 1016 | ||
1113 | /** | 1017 | /* current Tx Flow-control */ |
1114 | * ks8695_set_pause - Configure pause/flow-control | 1018 | ctrl = ks8695_readreg(ksp, KS8695_DTXC); |
1115 | * @ndev: The device to configure | 1019 | param->tx_pause = (ctrl & DTXC_TFCE); |
1116 | * @param: The pause parameters to set | ||
1117 | * | ||
1118 | * TODO: Implement this | ||
1119 | */ | ||
1120 | static int | ||
1121 | ks8695_set_pause(struct net_device *ndev, struct ethtool_pauseparam *param) | ||
1122 | { | ||
1123 | return -EOPNOTSUPP; | ||
1124 | } | 1020 | } |
1125 | 1021 | ||
1126 | /** | 1022 | /** |
@@ -1140,12 +1036,17 @@ ks8695_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info) | |||
1140 | static const struct ethtool_ops ks8695_ethtool_ops = { | 1036 | static const struct ethtool_ops ks8695_ethtool_ops = { |
1141 | .get_msglevel = ks8695_get_msglevel, | 1037 | .get_msglevel = ks8695_get_msglevel, |
1142 | .set_msglevel = ks8695_set_msglevel, | 1038 | .set_msglevel = ks8695_set_msglevel, |
1143 | .get_settings = ks8695_get_settings, | 1039 | .get_drvinfo = ks8695_get_drvinfo, |
1144 | .set_settings = ks8695_set_settings, | 1040 | }; |
1145 | .nway_reset = ks8695_nwayreset, | 1041 | |
1146 | .get_link = ks8695_get_link, | 1042 | static const struct ethtool_ops ks8695_wan_ethtool_ops = { |
1147 | .get_pauseparam = ks8695_get_pause, | 1043 | .get_msglevel = ks8695_get_msglevel, |
1148 | .set_pauseparam = ks8695_set_pause, | 1044 | .set_msglevel = ks8695_set_msglevel, |
1045 | .get_settings = ks8695_wan_get_settings, | ||
1046 | .set_settings = ks8695_wan_set_settings, | ||
1047 | .nway_reset = ks8695_wan_nwayreset, | ||
1048 | .get_link = ethtool_op_get_link, | ||
1049 | .get_pauseparam = ks8695_wan_get_pause, | ||
1149 | .get_drvinfo = ks8695_get_drvinfo, | 1050 | .get_drvinfo = ks8695_get_drvinfo, |
1150 | }; | 1051 | }; |
1151 | 1052 | ||
@@ -1541,7 +1442,6 @@ ks8695_probe(struct platform_device *pdev) | |||
1541 | 1442 | ||
1542 | /* driver system setup */ | 1443 | /* driver system setup */ |
1543 | ndev->netdev_ops = &ks8695_netdev_ops; | 1444 | ndev->netdev_ops = &ks8695_netdev_ops; |
1544 | SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops); | ||
1545 | ndev->watchdog_timeo = msecs_to_jiffies(watchdog); | 1445 | ndev->watchdog_timeo = msecs_to_jiffies(watchdog); |
1546 | 1446 | ||
1547 | netif_napi_add(ndev, &ksp->napi, ks8695_poll, NAPI_WEIGHT); | 1447 | netif_napi_add(ndev, &ksp->napi, ks8695_poll, NAPI_WEIGHT); |
@@ -1608,12 +1508,15 @@ ks8695_probe(struct platform_device *pdev) | |||
1608 | if (ksp->phyiface_regs && ksp->link_irq == -1) { | 1508 | if (ksp->phyiface_regs && ksp->link_irq == -1) { |
1609 | ks8695_init_switch(ksp); | 1509 | ks8695_init_switch(ksp); |
1610 | ksp->dtype = KS8695_DTYPE_LAN; | 1510 | ksp->dtype = KS8695_DTYPE_LAN; |
1511 | SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops); | ||
1611 | } else if (ksp->phyiface_regs && ksp->link_irq != -1) { | 1512 | } else if (ksp->phyiface_regs && ksp->link_irq != -1) { |
1612 | ks8695_init_wan_phy(ksp); | 1513 | ks8695_init_wan_phy(ksp); |
1613 | ksp->dtype = KS8695_DTYPE_WAN; | 1514 | ksp->dtype = KS8695_DTYPE_WAN; |
1515 | SET_ETHTOOL_OPS(ndev, &ks8695_wan_ethtool_ops); | ||
1614 | } else { | 1516 | } else { |
1615 | /* No initialisation since HPNA does not have a PHY */ | 1517 | /* No initialisation since HPNA does not have a PHY */ |
1616 | ksp->dtype = KS8695_DTYPE_HPNA; | 1518 | ksp->dtype = KS8695_DTYPE_HPNA; |
1519 | SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops); | ||
1617 | } | 1520 | } |
1618 | 1521 | ||
1619 | /* And bring up the net_device with the net core */ | 1522 | /* And bring up the net_device with the net core */ |
@@ -1742,7 +1645,7 @@ ks8695_cleanup(void) | |||
1742 | module_init(ks8695_init); | 1645 | module_init(ks8695_init); |
1743 | module_exit(ks8695_cleanup); | 1646 | module_exit(ks8695_cleanup); |
1744 | 1647 | ||
1745 | MODULE_AUTHOR("Simtec Electronics") | 1648 | MODULE_AUTHOR("Simtec Electronics"); |
1746 | MODULE_DESCRIPTION("Micrel KS8695 (Centaur) Ethernet driver"); | 1649 | MODULE_DESCRIPTION("Micrel KS8695 (Centaur) Ethernet driver"); |
1747 | MODULE_LICENSE("GPL"); | 1650 | MODULE_LICENSE("GPL"); |
1748 | MODULE_ALIAS("platform:" MODULENAME); | 1651 | MODULE_ALIAS("platform:" MODULENAME); |