diff options
| author | Esben Haabendal <esben@geanix.com> | 2019-04-30 03:17:49 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2019-05-01 14:33:30 -0400 |
| commit | 8425c41d1ef762cc15d9501d7117f009a79f3fe9 (patch) | |
| tree | 5b4a099ad4cee840a745ef01c87d602b527773f3 /drivers/net/ethernet | |
| parent | a63625d2a0e794f9a348a7119e50b0a56cbd6a18 (diff) | |
net: ll_temac: Extend support to non-device-tree platforms
Support initialization with platdata, so the driver can be used on
non-device-tree platforms.
For currently supported device-tree platforms, the driver should behave
as before.
Signed-off-by: Esben Haabendal <esben@geanix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet')
| -rw-r--r-- | drivers/net/ethernet/xilinx/ll_temac.h | 3 | ||||
| -rw-r--r-- | drivers/net/ethernet/xilinx/ll_temac_main.c | 187 | ||||
| -rw-r--r-- | drivers/net/ethernet/xilinx/ll_temac_mdio.c | 23 |
3 files changed, 147 insertions, 66 deletions
diff --git a/drivers/net/ethernet/xilinx/ll_temac.h b/drivers/net/ethernet/xilinx/ll_temac.h index 45575788ed54..e338b4fa3c60 100644 --- a/drivers/net/ethernet/xilinx/ll_temac.h +++ b/drivers/net/ethernet/xilinx/ll_temac.h | |||
| @@ -334,6 +334,9 @@ struct temac_local { | |||
| 334 | 334 | ||
| 335 | /* Connection to PHY device */ | 335 | /* Connection to PHY device */ |
| 336 | struct device_node *phy_node; | 336 | struct device_node *phy_node; |
| 337 | /* For non-device-tree devices */ | ||
| 338 | char phy_name[MII_BUS_ID_SIZE + 3]; | ||
| 339 | phy_interface_t phy_interface; | ||
| 337 | 340 | ||
| 338 | /* MDIO bus data */ | 341 | /* MDIO bus data */ |
| 339 | struct mii_bus *mii_bus; /* MII bus reference */ | 342 | struct mii_bus *mii_bus; /* MII bus reference */ |
diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c index c4e85a96df75..fddd1b3ac194 100644 --- a/drivers/net/ethernet/xilinx/ll_temac_main.c +++ b/drivers/net/ethernet/xilinx/ll_temac_main.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
| 34 | #include <linux/mutex.h> | 34 | #include <linux/mutex.h> |
| 35 | #include <linux/netdevice.h> | 35 | #include <linux/netdevice.h> |
| 36 | #include <linux/if_ether.h> | ||
| 36 | #include <linux/of.h> | 37 | #include <linux/of.h> |
| 37 | #include <linux/of_device.h> | 38 | #include <linux/of_device.h> |
| 38 | #include <linux/of_irq.h> | 39 | #include <linux/of_irq.h> |
| @@ -51,6 +52,7 @@ | |||
| 51 | #include <linux/slab.h> | 52 | #include <linux/slab.h> |
| 52 | #include <linux/interrupt.h> | 53 | #include <linux/interrupt.h> |
| 53 | #include <linux/dma-mapping.h> | 54 | #include <linux/dma-mapping.h> |
| 55 | #include <linux/platform_data/xilinx-ll-temac.h> | ||
| 54 | 56 | ||
| 55 | #include "ll_temac.h" | 57 | #include "ll_temac.h" |
| 56 | 58 | ||
| @@ -187,7 +189,7 @@ static int temac_dcr_setup(struct temac_local *lp, struct platform_device *op, | |||
| 187 | 189 | ||
| 188 | /* | 190 | /* |
| 189 | * temac_dcr_setup - This is a stub for when DCR is not supported, | 191 | * temac_dcr_setup - This is a stub for when DCR is not supported, |
| 190 | * such as with MicroBlaze | 192 | * such as with MicroBlaze and x86 |
| 191 | */ | 193 | */ |
| 192 | static int temac_dcr_setup(struct temac_local *lp, struct platform_device *op, | 194 | static int temac_dcr_setup(struct temac_local *lp, struct platform_device *op, |
| 193 | struct device_node *np) | 195 | struct device_node *np) |
| @@ -857,7 +859,14 @@ static int temac_open(struct net_device *ndev) | |||
| 857 | dev_err(lp->dev, "of_phy_connect() failed\n"); | 859 | dev_err(lp->dev, "of_phy_connect() failed\n"); |
| 858 | return -ENODEV; | 860 | return -ENODEV; |
| 859 | } | 861 | } |
| 860 | 862 | phy_start(phydev); | |
| 863 | } else if (strlen(lp->phy_name) > 0) { | ||
| 864 | phydev = phy_connect(lp->ndev, lp->phy_name, temac_adjust_link, | ||
| 865 | lp->phy_interface); | ||
| 866 | if (!phydev) { | ||
| 867 | dev_err(lp->dev, "phy_connect() failed\n"); | ||
| 868 | return -ENODEV; | ||
| 869 | } | ||
| 861 | phy_start(phydev); | 870 | phy_start(phydev); |
| 862 | } | 871 | } |
| 863 | 872 | ||
| @@ -977,11 +986,13 @@ static const struct ethtool_ops temac_ethtool_ops = { | |||
| 977 | .set_link_ksettings = phy_ethtool_set_link_ksettings, | 986 | .set_link_ksettings = phy_ethtool_set_link_ksettings, |
| 978 | }; | 987 | }; |
| 979 | 988 | ||
| 980 | static int temac_of_probe(struct platform_device *op) | 989 | static int temac_probe(struct platform_device *pdev) |
| 981 | { | 990 | { |
| 982 | struct device_node *np; | 991 | struct ll_temac_platform_data *pdata = dev_get_platdata(&pdev->dev); |
| 992 | struct device_node *temac_np = dev_of_node(&pdev->dev), *dma_np; | ||
| 983 | struct temac_local *lp; | 993 | struct temac_local *lp; |
| 984 | struct net_device *ndev; | 994 | struct net_device *ndev; |
| 995 | struct resource *res; | ||
| 985 | const void *addr; | 996 | const void *addr; |
| 986 | __be32 *p; | 997 | __be32 *p; |
| 987 | int rc = 0; | 998 | int rc = 0; |
| @@ -991,8 +1002,8 @@ static int temac_of_probe(struct platform_device *op) | |||
| 991 | if (!ndev) | 1002 | if (!ndev) |
| 992 | return -ENOMEM; | 1003 | return -ENOMEM; |
| 993 | 1004 | ||
| 994 | platform_set_drvdata(op, ndev); | 1005 | platform_set_drvdata(pdev, ndev); |
| 995 | SET_NETDEV_DEV(ndev, &op->dev); | 1006 | SET_NETDEV_DEV(ndev, &pdev->dev); |
| 996 | ndev->flags &= ~IFF_MULTICAST; /* clear multicast */ | 1007 | ndev->flags &= ~IFF_MULTICAST; /* clear multicast */ |
| 997 | ndev->features = NETIF_F_SG; | 1008 | ndev->features = NETIF_F_SG; |
| 998 | ndev->netdev_ops = &temac_netdev_ops; | 1009 | ndev->netdev_ops = &temac_netdev_ops; |
| @@ -1014,79 +1025,129 @@ static int temac_of_probe(struct platform_device *op) | |||
| 1014 | /* setup temac private info structure */ | 1025 | /* setup temac private info structure */ |
| 1015 | lp = netdev_priv(ndev); | 1026 | lp = netdev_priv(ndev); |
| 1016 | lp->ndev = ndev; | 1027 | lp->ndev = ndev; |
| 1017 | lp->dev = &op->dev; | 1028 | lp->dev = &pdev->dev; |
| 1018 | lp->options = XTE_OPTION_DEFAULTS; | 1029 | lp->options = XTE_OPTION_DEFAULTS; |
| 1019 | spin_lock_init(&lp->rx_lock); | 1030 | spin_lock_init(&lp->rx_lock); |
| 1020 | mutex_init(&lp->indirect_mutex); | 1031 | mutex_init(&lp->indirect_mutex); |
| 1021 | 1032 | ||
| 1022 | /* map device registers */ | 1033 | /* map device registers */ |
| 1023 | lp->regs = devm_of_iomap(&op->dev, op->dev.of_node, 0, NULL); | 1034 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 1024 | if (!lp->regs) { | 1035 | lp->regs = devm_ioremap_nocache(&pdev->dev, res->start, |
| 1025 | dev_err(&op->dev, "could not map temac regs.\n"); | 1036 | resource_size(res)); |
| 1026 | return -ENOMEM; | 1037 | if (IS_ERR(lp->regs)) { |
| 1038 | dev_err(&pdev->dev, "could not map TEMAC registers\n"); | ||
| 1039 | return PTR_ERR(lp->regs); | ||
| 1027 | } | 1040 | } |
| 1028 | 1041 | ||
| 1029 | /* Setup checksum offload, but default to off if not specified */ | 1042 | /* Setup checksum offload, but default to off if not specified */ |
| 1030 | lp->temac_features = 0; | 1043 | lp->temac_features = 0; |
| 1031 | p = (__be32 *)of_get_property(op->dev.of_node, "xlnx,txcsum", NULL); | 1044 | if (temac_np) { |
| 1032 | if (p && be32_to_cpu(*p)) { | 1045 | p = (__be32 *)of_get_property(temac_np, "xlnx,txcsum", NULL); |
| 1033 | lp->temac_features |= TEMAC_FEATURE_TX_CSUM; | 1046 | if (p && be32_to_cpu(*p)) |
| 1047 | lp->temac_features |= TEMAC_FEATURE_TX_CSUM; | ||
| 1048 | p = (__be32 *)of_get_property(temac_np, "xlnx,rxcsum", NULL); | ||
| 1049 | if (p && be32_to_cpu(*p)) | ||
| 1050 | lp->temac_features |= TEMAC_FEATURE_RX_CSUM; | ||
| 1051 | } else if (pdata) { | ||
| 1052 | if (pdata->txcsum) | ||
| 1053 | lp->temac_features |= TEMAC_FEATURE_TX_CSUM; | ||
| 1054 | if (pdata->rxcsum) | ||
| 1055 | lp->temac_features |= TEMAC_FEATURE_RX_CSUM; | ||
| 1056 | } | ||
| 1057 | if (lp->temac_features & TEMAC_FEATURE_TX_CSUM) | ||
| 1034 | /* Can checksum TCP/UDP over IPv4. */ | 1058 | /* Can checksum TCP/UDP over IPv4. */ |
| 1035 | ndev->features |= NETIF_F_IP_CSUM; | 1059 | ndev->features |= NETIF_F_IP_CSUM; |
| 1036 | } | ||
| 1037 | p = (__be32 *)of_get_property(op->dev.of_node, "xlnx,rxcsum", NULL); | ||
| 1038 | if (p && be32_to_cpu(*p)) | ||
| 1039 | lp->temac_features |= TEMAC_FEATURE_RX_CSUM; | ||
| 1040 | |||
| 1041 | /* Find the DMA node, map the DMA registers, and decode the DMA IRQs */ | ||
| 1042 | np = of_parse_phandle(op->dev.of_node, "llink-connected", 0); | ||
| 1043 | if (!np) { | ||
| 1044 | dev_err(&op->dev, "could not find DMA node\n"); | ||
| 1045 | return -ENODEV; | ||
| 1046 | } | ||
| 1047 | 1060 | ||
| 1048 | /* Setup the DMA register accesses, could be DCR or memory mapped */ | 1061 | /* Setup LocalLink DMA */ |
| 1049 | if (temac_dcr_setup(lp, op, np)) { | 1062 | if (temac_np) { |
| 1063 | /* Find the DMA node, map the DMA registers, and | ||
| 1064 | * decode the DMA IRQs. | ||
| 1065 | */ | ||
| 1066 | dma_np = of_parse_phandle(temac_np, "llink-connected", 0); | ||
| 1067 | if (!dma_np) { | ||
| 1068 | dev_err(&pdev->dev, "could not find DMA node\n"); | ||
| 1069 | return -ENODEV; | ||
| 1070 | } | ||
| 1050 | 1071 | ||
| 1051 | /* no DCR in the device tree, try non-DCR */ | 1072 | /* Setup the DMA register accesses, could be DCR or |
| 1052 | lp->sdma_regs = devm_of_iomap(&op->dev, np, 0, NULL); | 1073 | * memory mapped. |
| 1053 | if (lp->sdma_regs) { | 1074 | */ |
| 1075 | if (temac_dcr_setup(lp, pdev, dma_np)) { | ||
| 1076 | /* no DCR in the device tree, try non-DCR */ | ||
| 1077 | lp->sdma_regs = devm_of_iomap(&pdev->dev, dma_np, 0, | ||
| 1078 | NULL); | ||
| 1079 | if (IS_ERR(lp->sdma_regs)) { | ||
| 1080 | dev_err(&pdev->dev, | ||
| 1081 | "unable to map DMA registers\n"); | ||
| 1082 | of_node_put(dma_np); | ||
| 1083 | return PTR_ERR(lp->sdma_regs); | ||
| 1084 | } | ||
| 1054 | lp->dma_in = temac_dma_in32; | 1085 | lp->dma_in = temac_dma_in32; |
| 1055 | lp->dma_out = temac_dma_out32; | 1086 | lp->dma_out = temac_dma_out32; |
| 1056 | dev_dbg(&op->dev, "MEM base: %p\n", lp->sdma_regs); | 1087 | dev_dbg(&pdev->dev, "MEM base: %p\n", lp->sdma_regs); |
| 1057 | } else { | ||
| 1058 | dev_err(&op->dev, "unable to map DMA registers\n"); | ||
| 1059 | of_node_put(np); | ||
| 1060 | return -ENOMEM; | ||
| 1061 | } | 1088 | } |
| 1062 | } | ||
| 1063 | |||
| 1064 | lp->rx_irq = irq_of_parse_and_map(np, 0); | ||
| 1065 | lp->tx_irq = irq_of_parse_and_map(np, 1); | ||
| 1066 | 1089 | ||
| 1067 | of_node_put(np); /* Finished with the DMA node; drop the reference */ | 1090 | /* Get DMA RX and TX interrupts */ |
| 1091 | lp->rx_irq = irq_of_parse_and_map(dma_np, 0); | ||
| 1092 | lp->tx_irq = irq_of_parse_and_map(dma_np, 1); | ||
| 1093 | |||
| 1094 | /* Finished with the DMA node; drop the reference */ | ||
| 1095 | of_node_put(dma_np); | ||
| 1096 | } else if (pdata) { | ||
| 1097 | /* 2nd memory resource specifies DMA registers */ | ||
| 1098 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
| 1099 | lp->sdma_regs = devm_ioremap_nocache(&pdev->dev, res->start, | ||
| 1100 | resource_size(res)); | ||
| 1101 | if (IS_ERR(lp->sdma_regs)) { | ||
| 1102 | dev_err(&pdev->dev, | ||
| 1103 | "could not map DMA registers\n"); | ||
| 1104 | return PTR_ERR(lp->sdma_regs); | ||
| 1105 | } | ||
| 1106 | lp->dma_in = temac_dma_in32; | ||
| 1107 | lp->dma_out = temac_dma_out32; | ||
| 1068 | 1108 | ||
| 1069 | if (!lp->rx_irq || !lp->tx_irq) { | 1109 | /* Get DMA RX and TX interrupts */ |
| 1070 | dev_err(&op->dev, "could not determine irqs\n"); | 1110 | lp->rx_irq = platform_get_irq(pdev, 0); |
| 1071 | return -ENOMEM; | 1111 | lp->tx_irq = platform_get_irq(pdev, 1); |
| 1072 | } | 1112 | } |
| 1073 | 1113 | ||
| 1114 | /* Error handle returned DMA RX and TX interrupts */ | ||
| 1115 | if (lp->rx_irq < 0) { | ||
| 1116 | if (lp->rx_irq != -EPROBE_DEFER) | ||
| 1117 | dev_err(&pdev->dev, "could not get DMA RX irq\n"); | ||
| 1118 | return lp->rx_irq; | ||
| 1119 | } | ||
| 1120 | if (lp->tx_irq < 0) { | ||
| 1121 | if (lp->tx_irq != -EPROBE_DEFER) | ||
| 1122 | dev_err(&pdev->dev, "could not get DMA TX irq\n"); | ||
| 1123 | return lp->tx_irq; | ||
| 1124 | } | ||
| 1074 | 1125 | ||
| 1075 | /* Retrieve the MAC address */ | 1126 | if (temac_np) { |
| 1076 | addr = of_get_mac_address(op->dev.of_node); | 1127 | /* Retrieve the MAC address */ |
| 1077 | if (!addr) { | 1128 | addr = of_get_mac_address(temac_np); |
| 1078 | dev_err(&op->dev, "could not find MAC address\n"); | 1129 | if (!addr) { |
| 1079 | return -ENODEV; | 1130 | dev_err(&pdev->dev, "could not find MAC address\n"); |
| 1131 | return -ENODEV; | ||
| 1132 | } | ||
| 1133 | temac_init_mac_address(ndev, addr); | ||
| 1134 | } else if (pdata) { | ||
| 1135 | temac_init_mac_address(ndev, pdata->mac_addr); | ||
| 1080 | } | 1136 | } |
| 1081 | temac_init_mac_address(ndev, addr); | ||
| 1082 | 1137 | ||
| 1083 | rc = temac_mdio_setup(lp, pdev); | 1138 | rc = temac_mdio_setup(lp, pdev); |
| 1084 | if (rc) | 1139 | if (rc) |
| 1085 | dev_warn(&op->dev, "error registering MDIO bus\n"); | 1140 | dev_warn(&pdev->dev, "error registering MDIO bus\n"); |
| 1086 | 1141 | ||
| 1087 | lp->phy_node = of_parse_phandle(op->dev.of_node, "phy-handle", 0); | 1142 | if (temac_np) { |
| 1088 | if (lp->phy_node) | 1143 | lp->phy_node = of_parse_phandle(temac_np, "phy-handle", 0); |
| 1089 | dev_dbg(lp->dev, "using PHY node %pOF (%p)\n", np, np); | 1144 | if (lp->phy_node) |
| 1145 | dev_dbg(lp->dev, "using PHY node %pOF\n", temac_np); | ||
| 1146 | } else if (pdata) { | ||
| 1147 | snprintf(lp->phy_name, sizeof(lp->phy_name), | ||
| 1148 | PHY_ID_FMT, lp->mii_bus->id, pdata->phy_addr); | ||
| 1149 | lp->phy_interface = pdata->phy_interface; | ||
| 1150 | } | ||
| 1090 | 1151 | ||
| 1091 | /* Add the device attributes */ | 1152 | /* Add the device attributes */ |
| 1092 | rc = sysfs_create_group(&lp->dev->kobj, &temac_attr_group); | 1153 | rc = sysfs_create_group(&lp->dev->kobj, &temac_attr_group); |
| @@ -1106,19 +1167,21 @@ static int temac_of_probe(struct platform_device *op) | |||
| 1106 | err_register_ndev: | 1167 | err_register_ndev: |
| 1107 | sysfs_remove_group(&lp->dev->kobj, &temac_attr_group); | 1168 | sysfs_remove_group(&lp->dev->kobj, &temac_attr_group); |
| 1108 | err_sysfs_create: | 1169 | err_sysfs_create: |
| 1109 | of_node_put(lp->phy_node); | 1170 | if (lp->phy_node) |
| 1171 | of_node_put(lp->phy_node); | ||
| 1110 | temac_mdio_teardown(lp); | 1172 | temac_mdio_teardown(lp); |
| 1111 | return rc; | 1173 | return rc; |
| 1112 | } | 1174 | } |
| 1113 | 1175 | ||
| 1114 | static int temac_of_remove(struct platform_device *op) | 1176 | static int temac_remove(struct platform_device *pdev) |
| 1115 | { | 1177 | { |
| 1116 | struct net_device *ndev = platform_get_drvdata(op); | 1178 | struct net_device *ndev = platform_get_drvdata(pdev); |
| 1117 | struct temac_local *lp = netdev_priv(ndev); | 1179 | struct temac_local *lp = netdev_priv(ndev); |
| 1118 | 1180 | ||
| 1119 | unregister_netdev(ndev); | 1181 | unregister_netdev(ndev); |
| 1120 | sysfs_remove_group(&lp->dev->kobj, &temac_attr_group); | 1182 | sysfs_remove_group(&lp->dev->kobj, &temac_attr_group); |
| 1121 | of_node_put(lp->phy_node); | 1183 | if (lp->phy_node) |
| 1184 | of_node_put(lp->phy_node); | ||
| 1122 | temac_mdio_teardown(lp); | 1185 | temac_mdio_teardown(lp); |
| 1123 | return 0; | 1186 | return 0; |
| 1124 | } | 1187 | } |
| @@ -1132,16 +1195,16 @@ static const struct of_device_id temac_of_match[] = { | |||
| 1132 | }; | 1195 | }; |
| 1133 | MODULE_DEVICE_TABLE(of, temac_of_match); | 1196 | MODULE_DEVICE_TABLE(of, temac_of_match); |
| 1134 | 1197 | ||
| 1135 | static struct platform_driver temac_of_driver = { | 1198 | static struct platform_driver temac_driver = { |
| 1136 | .probe = temac_of_probe, | 1199 | .probe = temac_probe, |
| 1137 | .remove = temac_of_remove, | 1200 | .remove = temac_remove, |
| 1138 | .driver = { | 1201 | .driver = { |
| 1139 | .name = "xilinx_temac", | 1202 | .name = "xilinx_temac", |
| 1140 | .of_match_table = temac_of_match, | 1203 | .of_match_table = temac_of_match, |
| 1141 | }, | 1204 | }, |
| 1142 | }; | 1205 | }; |
| 1143 | 1206 | ||
| 1144 | module_platform_driver(temac_of_driver); | 1207 | module_platform_driver(temac_driver); |
| 1145 | 1208 | ||
| 1146 | MODULE_DESCRIPTION("Xilinx LL_TEMAC Ethernet driver"); | 1209 | MODULE_DESCRIPTION("Xilinx LL_TEMAC Ethernet driver"); |
| 1147 | MODULE_AUTHOR("Yoshio Kashiwagi"); | 1210 | MODULE_AUTHOR("Yoshio Kashiwagi"); |
diff --git a/drivers/net/ethernet/xilinx/ll_temac_mdio.c b/drivers/net/ethernet/xilinx/ll_temac_mdio.c index a0b365e43ebf..c5307e5b8e0a 100644 --- a/drivers/net/ethernet/xilinx/ll_temac_mdio.c +++ b/drivers/net/ethernet/xilinx/ll_temac_mdio.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/of_address.h> | 14 | #include <linux/of_address.h> |
| 15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| 16 | #include <linux/of_mdio.h> | 16 | #include <linux/of_mdio.h> |
| 17 | #include <linux/platform_data/xilinx-ll-temac.h> | ||
| 17 | 18 | ||
| 18 | #include "ll_temac.h" | 19 | #include "ll_temac.h" |
| 19 | 20 | ||
| @@ -59,6 +60,7 @@ static int temac_mdio_write(struct mii_bus *bus, int phy_id, int reg, u16 val) | |||
| 59 | 60 | ||
| 60 | int temac_mdio_setup(struct temac_local *lp, struct platform_device *pdev) | 61 | int temac_mdio_setup(struct temac_local *lp, struct platform_device *pdev) |
| 61 | { | 62 | { |
| 63 | struct ll_temac_platform_data *pdata = dev_get_platdata(&pdev->dev); | ||
| 62 | struct device_node *np = dev_of_node(&pdev->dev); | 64 | struct device_node *np = dev_of_node(&pdev->dev); |
| 63 | struct mii_bus *bus; | 65 | struct mii_bus *bus; |
| 64 | u32 bus_hz; | 66 | u32 bus_hz; |
| @@ -66,9 +68,16 @@ int temac_mdio_setup(struct temac_local *lp, struct platform_device *pdev) | |||
| 66 | int rc; | 68 | int rc; |
| 67 | struct resource res; | 69 | struct resource res; |
| 68 | 70 | ||
| 71 | /* Get MDIO bus frequency (if specified) */ | ||
| 72 | bus_hz = 0; | ||
| 73 | if (np) | ||
| 74 | of_property_read_u32(np, "clock-frequency", &bus_hz); | ||
| 75 | else if (pdata) | ||
| 76 | bus_hz = pdata->mdio_clk_freq; | ||
| 77 | |||
| 69 | /* Calculate a reasonable divisor for the clock rate */ | 78 | /* Calculate a reasonable divisor for the clock rate */ |
| 70 | clk_div = 0x3f; /* worst-case default setting */ | 79 | clk_div = 0x3f; /* worst-case default setting */ |
| 71 | if (of_property_read_u32(np, "clock-frequency", &bus_hz) == 0) { | 80 | if (bus_hz != 0) { |
| 72 | clk_div = bus_hz / (2500 * 1000 * 2) - 1; | 81 | clk_div = bus_hz / (2500 * 1000 * 2) - 1; |
| 73 | if (clk_div < 1) | 82 | if (clk_div < 1) |
| 74 | clk_div = 1; | 83 | clk_div = 1; |
| @@ -86,9 +95,15 @@ int temac_mdio_setup(struct temac_local *lp, struct platform_device *pdev) | |||
| 86 | if (!bus) | 95 | if (!bus) |
| 87 | return -ENOMEM; | 96 | return -ENOMEM; |
| 88 | 97 | ||
| 89 | of_address_to_resource(np, 0, &res); | 98 | if (np) { |
| 90 | snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx", | 99 | of_address_to_resource(np, 0, &res); |
| 91 | (unsigned long long)res.start); | 100 | snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx", |
| 101 | (unsigned long long)res.start); | ||
| 102 | } else if (pdata && pdata->mdio_bus_id >= 0) { | ||
| 103 | snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx", | ||
| 104 | pdata->mdio_bus_id); | ||
| 105 | } | ||
| 106 | |||
| 92 | bus->priv = lp; | 107 | bus->priv = lp; |
| 93 | bus->name = "Xilinx TEMAC MDIO"; | 108 | bus->name = "Xilinx TEMAC MDIO"; |
| 94 | bus->read = temac_mdio_read; | 109 | bus->read = temac_mdio_read; |
