aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
authorEsben Haabendal <esben@geanix.com>2019-04-30 03:17:49 -0400
committerDavid S. Miller <davem@davemloft.net>2019-05-01 14:33:30 -0400
commit8425c41d1ef762cc15d9501d7117f009a79f3fe9 (patch)
tree5b4a099ad4cee840a745ef01c87d602b527773f3 /drivers/net/ethernet
parenta63625d2a0e794f9a348a7119e50b0a56cbd6a18 (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.h3
-rw-r--r--drivers/net/ethernet/xilinx/ll_temac_main.c187
-rw-r--r--drivers/net/ethernet/xilinx/ll_temac_mdio.c23
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 */
192static int temac_dcr_setup(struct temac_local *lp, struct platform_device *op, 194static 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
980static int temac_of_probe(struct platform_device *op) 989static 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)
1106err_register_ndev: 1167err_register_ndev:
1107 sysfs_remove_group(&lp->dev->kobj, &temac_attr_group); 1168 sysfs_remove_group(&lp->dev->kobj, &temac_attr_group);
1108err_sysfs_create: 1169err_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
1114static int temac_of_remove(struct platform_device *op) 1176static 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};
1133MODULE_DEVICE_TABLE(of, temac_of_match); 1196MODULE_DEVICE_TABLE(of, temac_of_match);
1134 1197
1135static struct platform_driver temac_of_driver = { 1198static 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
1144module_platform_driver(temac_of_driver); 1207module_platform_driver(temac_driver);
1145 1208
1146MODULE_DESCRIPTION("Xilinx LL_TEMAC Ethernet driver"); 1209MODULE_DESCRIPTION("Xilinx LL_TEMAC Ethernet driver");
1147MODULE_AUTHOR("Yoshio Kashiwagi"); 1210MODULE_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
60int temac_mdio_setup(struct temac_local *lp, struct platform_device *pdev) 61int 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;