diff options
-rw-r--r-- | drivers/net/ethernet/ethoc.c | 32 | ||||
-rw-r--r-- | include/net/ethoc.h | 1 |
2 files changed, 31 insertions, 2 deletions
diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c index 0a8533c0c01a..55e0fa03dc90 100644 --- a/drivers/net/ethernet/ethoc.c +++ b/drivers/net/ethernet/ethoc.c | |||
@@ -13,6 +13,7 @@ | |||
13 | 13 | ||
14 | #include <linux/dma-mapping.h> | 14 | #include <linux/dma-mapping.h> |
15 | #include <linux/etherdevice.h> | 15 | #include <linux/etherdevice.h> |
16 | #include <linux/clk.h> | ||
16 | #include <linux/crc32.h> | 17 | #include <linux/crc32.h> |
17 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
18 | #include <linux/io.h> | 19 | #include <linux/io.h> |
@@ -219,6 +220,7 @@ struct ethoc { | |||
219 | 220 | ||
220 | struct phy_device *phy; | 221 | struct phy_device *phy; |
221 | struct mii_bus *mdio; | 222 | struct mii_bus *mdio; |
223 | struct clk *clk; | ||
222 | s8 phy_id; | 224 | s8 phy_id; |
223 | }; | 225 | }; |
224 | 226 | ||
@@ -1021,6 +1023,8 @@ static int ethoc_probe(struct platform_device *pdev) | |||
1021 | int num_bd; | 1023 | int num_bd; |
1022 | int ret = 0; | 1024 | int ret = 0; |
1023 | bool random_mac = false; | 1025 | bool random_mac = false; |
1026 | struct ethoc_platform_data *pdata = dev_get_platdata(&pdev->dev); | ||
1027 | u32 eth_clkfreq = pdata ? pdata->eth_clkfreq : 0; | ||
1024 | 1028 | ||
1025 | /* allocate networking device */ | 1029 | /* allocate networking device */ |
1026 | netdev = alloc_etherdev(sizeof(struct ethoc)); | 1030 | netdev = alloc_etherdev(sizeof(struct ethoc)); |
@@ -1135,8 +1139,7 @@ static int ethoc_probe(struct platform_device *pdev) | |||
1135 | } | 1139 | } |
1136 | 1140 | ||
1137 | /* Allow the platform setup code to pass in a MAC address. */ | 1141 | /* Allow the platform setup code to pass in a MAC address. */ |
1138 | if (dev_get_platdata(&pdev->dev)) { | 1142 | if (pdata) { |
1139 | struct ethoc_platform_data *pdata = dev_get_platdata(&pdev->dev); | ||
1140 | memcpy(netdev->dev_addr, pdata->hwaddr, IFHWADDRLEN); | 1143 | memcpy(netdev->dev_addr, pdata->hwaddr, IFHWADDRLEN); |
1141 | priv->phy_id = pdata->phy_id; | 1144 | priv->phy_id = pdata->phy_id; |
1142 | } else { | 1145 | } else { |
@@ -1174,6 +1177,27 @@ static int ethoc_probe(struct platform_device *pdev) | |||
1174 | if (random_mac) | 1177 | if (random_mac) |
1175 | netdev->addr_assign_type = NET_ADDR_RANDOM; | 1178 | netdev->addr_assign_type = NET_ADDR_RANDOM; |
1176 | 1179 | ||
1180 | /* Allow the platform setup code to adjust MII management bus clock. */ | ||
1181 | if (!eth_clkfreq) { | ||
1182 | struct clk *clk = devm_clk_get(&pdev->dev, NULL); | ||
1183 | |||
1184 | if (!IS_ERR(clk)) { | ||
1185 | priv->clk = clk; | ||
1186 | clk_prepare_enable(clk); | ||
1187 | eth_clkfreq = clk_get_rate(clk); | ||
1188 | } | ||
1189 | } | ||
1190 | if (eth_clkfreq) { | ||
1191 | u32 clkdiv = MIIMODER_CLKDIV(eth_clkfreq / 2500000 + 1); | ||
1192 | |||
1193 | if (!clkdiv) | ||
1194 | clkdiv = 2; | ||
1195 | dev_dbg(&pdev->dev, "setting MII clkdiv to %u\n", clkdiv); | ||
1196 | ethoc_write(priv, MIIMODER, | ||
1197 | (ethoc_read(priv, MIIMODER) & MIIMODER_NOPRE) | | ||
1198 | clkdiv); | ||
1199 | } | ||
1200 | |||
1177 | /* register MII bus */ | 1201 | /* register MII bus */ |
1178 | priv->mdio = mdiobus_alloc(); | 1202 | priv->mdio = mdiobus_alloc(); |
1179 | if (!priv->mdio) { | 1203 | if (!priv->mdio) { |
@@ -1239,6 +1263,8 @@ free_mdio: | |||
1239 | kfree(priv->mdio->irq); | 1263 | kfree(priv->mdio->irq); |
1240 | mdiobus_free(priv->mdio); | 1264 | mdiobus_free(priv->mdio); |
1241 | free: | 1265 | free: |
1266 | if (priv->clk) | ||
1267 | clk_disable_unprepare(priv->clk); | ||
1242 | free_netdev(netdev); | 1268 | free_netdev(netdev); |
1243 | out: | 1269 | out: |
1244 | return ret; | 1270 | return ret; |
@@ -1263,6 +1289,8 @@ static int ethoc_remove(struct platform_device *pdev) | |||
1263 | kfree(priv->mdio->irq); | 1289 | kfree(priv->mdio->irq); |
1264 | mdiobus_free(priv->mdio); | 1290 | mdiobus_free(priv->mdio); |
1265 | } | 1291 | } |
1292 | if (priv->clk) | ||
1293 | clk_disable_unprepare(priv->clk); | ||
1266 | unregister_netdev(netdev); | 1294 | unregister_netdev(netdev); |
1267 | free_netdev(netdev); | 1295 | free_netdev(netdev); |
1268 | } | 1296 | } |
diff --git a/include/net/ethoc.h b/include/net/ethoc.h index 96f3789b27bc..2a2d6bb34eb8 100644 --- a/include/net/ethoc.h +++ b/include/net/ethoc.h | |||
@@ -16,6 +16,7 @@ | |||
16 | struct ethoc_platform_data { | 16 | struct ethoc_platform_data { |
17 | u8 hwaddr[IFHWADDRLEN]; | 17 | u8 hwaddr[IFHWADDRLEN]; |
18 | s8 phy_id; | 18 | s8 phy_id; |
19 | u32 eth_clkfreq; | ||
19 | }; | 20 | }; |
20 | 21 | ||
21 | #endif /* !LINUX_NET_ETHOC_H */ | 22 | #endif /* !LINUX_NET_ETHOC_H */ |