|
@@ -62,6 +62,7 @@
|
|
#include <linux/of.h>
|
|
#include <linux/of.h>
|
|
#include <linux/of_address.h>
|
|
#include <linux/of_address.h>
|
|
#include <linux/of_device.h>
|
|
#include <linux/of_device.h>
|
|
|
|
+#include <linux/of_mdio.h>
|
|
#include <linux/of_irq.h>
|
|
#include <linux/of_irq.h>
|
|
#include <linux/of_net.h>
|
|
#include <linux/of_net.h>
|
|
|
|
|
|
@@ -343,9 +344,7 @@ struct emac_priv {
|
|
u32 multicast_hash_cnt[EMAC_NUM_MULTICAST_BITS];
|
|
u32 multicast_hash_cnt[EMAC_NUM_MULTICAST_BITS];
|
|
u32 rx_addr_type;
|
|
u32 rx_addr_type;
|
|
const char *phy_id;
|
|
const char *phy_id;
|
|
-#ifdef CONFIG_OF
|
|
|
|
struct device_node *phy_node;
|
|
struct device_node *phy_node;
|
|
-#endif
|
|
|
|
struct phy_device *phydev;
|
|
struct phy_device *phydev;
|
|
spinlock_t lock;
|
|
spinlock_t lock;
|
|
/*platform specific members*/
|
|
/*platform specific members*/
|
|
@@ -922,6 +921,16 @@ static void emac_int_disable(struct emac_priv *priv)
|
|
if (priv->int_disable)
|
|
if (priv->int_disable)
|
|
priv->int_disable();
|
|
priv->int_disable();
|
|
|
|
|
|
|
|
+ /* NOTE: Rx Threshold and Misc interrupts are not enabled */
|
|
|
|
+
|
|
|
|
+ /* ack rxen only then a new pulse will be generated */
|
|
|
|
+ emac_write(EMAC_DM646X_MACEOIVECTOR,
|
|
|
|
+ EMAC_DM646X_MAC_EOI_C0_RXEN);
|
|
|
|
+
|
|
|
|
+ /* ack txen- only then a new pulse will be generated */
|
|
|
|
+ emac_write(EMAC_DM646X_MACEOIVECTOR,
|
|
|
|
+ EMAC_DM646X_MAC_EOI_C0_TXEN);
|
|
|
|
+
|
|
local_irq_restore(flags);
|
|
local_irq_restore(flags);
|
|
|
|
|
|
} else {
|
|
} else {
|
|
@@ -951,15 +960,6 @@ static void emac_int_enable(struct emac_priv *priv)
|
|
* register */
|
|
* register */
|
|
|
|
|
|
/* NOTE: Rx Threshold and Misc interrupts are not enabled */
|
|
/* NOTE: Rx Threshold and Misc interrupts are not enabled */
|
|
-
|
|
|
|
- /* ack rxen only then a new pulse will be generated */
|
|
|
|
- emac_write(EMAC_DM646X_MACEOIVECTOR,
|
|
|
|
- EMAC_DM646X_MAC_EOI_C0_RXEN);
|
|
|
|
-
|
|
|
|
- /* ack txen- only then a new pulse will be generated */
|
|
|
|
- emac_write(EMAC_DM646X_MACEOIVECTOR,
|
|
|
|
- EMAC_DM646X_MAC_EOI_C0_TXEN);
|
|
|
|
-
|
|
|
|
} else {
|
|
} else {
|
|
/* Set DM644x control registers for interrupt control */
|
|
/* Set DM644x control registers for interrupt control */
|
|
emac_ctrl_write(EMAC_CTRL_EWCTL, 0x1);
|
|
emac_ctrl_write(EMAC_CTRL_EWCTL, 0x1);
|
|
@@ -1537,7 +1537,13 @@ static int emac_dev_open(struct net_device *ndev)
|
|
int i = 0;
|
|
int i = 0;
|
|
struct emac_priv *priv = netdev_priv(ndev);
|
|
struct emac_priv *priv = netdev_priv(ndev);
|
|
|
|
|
|
- pm_runtime_get(&priv->pdev->dev);
|
|
|
|
|
|
+ ret = pm_runtime_get_sync(&priv->pdev->dev);
|
|
|
|
+ if (ret < 0) {
|
|
|
|
+ pm_runtime_put_noidle(&priv->pdev->dev);
|
|
|
|
+ dev_err(&priv->pdev->dev, "%s: failed to get_sync(%d)\n",
|
|
|
|
+ __func__, ret);
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
|
|
netif_carrier_off(ndev);
|
|
netif_carrier_off(ndev);
|
|
for (cnt = 0; cnt < ETH_ALEN; cnt++)
|
|
for (cnt = 0; cnt < ETH_ALEN; cnt++)
|
|
@@ -1596,8 +1602,20 @@ static int emac_dev_open(struct net_device *ndev)
|
|
cpdma_ctlr_start(priv->dma);
|
|
cpdma_ctlr_start(priv->dma);
|
|
|
|
|
|
priv->phydev = NULL;
|
|
priv->phydev = NULL;
|
|
|
|
+
|
|
|
|
+ if (priv->phy_node) {
|
|
|
|
+ priv->phydev = of_phy_connect(ndev, priv->phy_node,
|
|
|
|
+ &emac_adjust_link, 0, 0);
|
|
|
|
+ if (!priv->phydev) {
|
|
|
|
+ dev_err(emac_dev, "could not connect to phy %s\n",
|
|
|
|
+ priv->phy_node->full_name);
|
|
|
|
+ ret = -ENODEV;
|
|
|
|
+ goto err;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
/* use the first phy on the bus if pdata did not give us a phy id */
|
|
/* use the first phy on the bus if pdata did not give us a phy id */
|
|
- if (!priv->phy_id) {
|
|
|
|
|
|
+ if (!priv->phydev && !priv->phy_id) {
|
|
struct device *phy;
|
|
struct device *phy;
|
|
|
|
|
|
phy = bus_find_device(&mdio_bus_type, NULL, NULL,
|
|
phy = bus_find_device(&mdio_bus_type, NULL, NULL,
|
|
@@ -1606,7 +1624,7 @@ static int emac_dev_open(struct net_device *ndev)
|
|
priv->phy_id = dev_name(phy);
|
|
priv->phy_id = dev_name(phy);
|
|
}
|
|
}
|
|
|
|
|
|
- if (priv->phy_id && *priv->phy_id) {
|
|
|
|
|
|
+ if (!priv->phydev && priv->phy_id && *priv->phy_id) {
|
|
priv->phydev = phy_connect(ndev, priv->phy_id,
|
|
priv->phydev = phy_connect(ndev, priv->phy_id,
|
|
&emac_adjust_link,
|
|
&emac_adjust_link,
|
|
PHY_INTERFACE_MODE_MII);
|
|
PHY_INTERFACE_MODE_MII);
|
|
@@ -1627,7 +1645,9 @@ static int emac_dev_open(struct net_device *ndev)
|
|
"(mii_bus:phy_addr=%s, id=%x)\n",
|
|
"(mii_bus:phy_addr=%s, id=%x)\n",
|
|
priv->phydev->drv->name, dev_name(&priv->phydev->dev),
|
|
priv->phydev->drv->name, dev_name(&priv->phydev->dev),
|
|
priv->phydev->phy_id);
|
|
priv->phydev->phy_id);
|
|
- } else {
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!priv->phydev) {
|
|
/* No PHY , fix the link, speed and duplex settings */
|
|
/* No PHY , fix the link, speed and duplex settings */
|
|
dev_notice(emac_dev, "no phy, defaulting to 100/full\n");
|
|
dev_notice(emac_dev, "no phy, defaulting to 100/full\n");
|
|
priv->link = 1;
|
|
priv->link = 1;
|
|
@@ -1724,6 +1744,15 @@ static struct net_device_stats *emac_dev_getnetstats(struct net_device *ndev)
|
|
struct emac_priv *priv = netdev_priv(ndev);
|
|
struct emac_priv *priv = netdev_priv(ndev);
|
|
u32 mac_control;
|
|
u32 mac_control;
|
|
u32 stats_clear_mask;
|
|
u32 stats_clear_mask;
|
|
|
|
+ int err;
|
|
|
|
+
|
|
|
|
+ err = pm_runtime_get_sync(&priv->pdev->dev);
|
|
|
|
+ if (err < 0) {
|
|
|
|
+ pm_runtime_put_noidle(&priv->pdev->dev);
|
|
|
|
+ dev_err(&priv->pdev->dev, "%s: failed to get_sync(%d)\n",
|
|
|
|
+ __func__, err);
|
|
|
|
+ return &ndev->stats;
|
|
|
|
+ }
|
|
|
|
|
|
/* update emac hardware stats and reset the registers*/
|
|
/* update emac hardware stats and reset the registers*/
|
|
|
|
|
|
@@ -1766,6 +1795,8 @@ static struct net_device_stats *emac_dev_getnetstats(struct net_device *ndev)
|
|
ndev->stats.tx_fifo_errors += emac_read(EMAC_TXUNDERRUN);
|
|
ndev->stats.tx_fifo_errors += emac_read(EMAC_TXUNDERRUN);
|
|
emac_write(EMAC_TXUNDERRUN, stats_clear_mask);
|
|
emac_write(EMAC_TXUNDERRUN, stats_clear_mask);
|
|
|
|
|
|
|
|
+ pm_runtime_put(&priv->pdev->dev);
|
|
|
|
+
|
|
return &ndev->stats;
|
|
return &ndev->stats;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1859,7 +1890,7 @@ davinci_emac_of_get_pdata(struct platform_device *pdev, struct emac_priv *priv)
|
|
static int davinci_emac_probe(struct platform_device *pdev)
|
|
static int davinci_emac_probe(struct platform_device *pdev)
|
|
{
|
|
{
|
|
int rc = 0;
|
|
int rc = 0;
|
|
- struct resource *res;
|
|
|
|
|
|
+ struct resource *res, *res_ctrl;
|
|
struct net_device *ndev;
|
|
struct net_device *ndev;
|
|
struct emac_priv *priv;
|
|
struct emac_priv *priv;
|
|
unsigned long hw_ram_addr;
|
|
unsigned long hw_ram_addr;
|
|
@@ -1876,6 +1907,7 @@ static int davinci_emac_probe(struct platform_device *pdev)
|
|
return -EBUSY;
|
|
return -EBUSY;
|
|
}
|
|
}
|
|
emac_bus_frequency = clk_get_rate(emac_clk);
|
|
emac_bus_frequency = clk_get_rate(emac_clk);
|
|
|
|
+ devm_clk_put(&pdev->dev, emac_clk);
|
|
|
|
|
|
/* TODO: Probe PHY here if possible */
|
|
/* TODO: Probe PHY here if possible */
|
|
|
|
|
|
@@ -1917,11 +1949,20 @@ static int davinci_emac_probe(struct platform_device *pdev)
|
|
rc = PTR_ERR(priv->remap_addr);
|
|
rc = PTR_ERR(priv->remap_addr);
|
|
goto no_pdata;
|
|
goto no_pdata;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ res_ctrl = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
|
|
|
+ if (res_ctrl) {
|
|
|
|
+ priv->ctrl_base =
|
|
|
|
+ devm_ioremap_resource(&pdev->dev, res_ctrl);
|
|
|
|
+ if (IS_ERR(priv->ctrl_base))
|
|
|
|
+ goto no_pdata;
|
|
|
|
+ } else {
|
|
|
|
+ priv->ctrl_base = priv->remap_addr + pdata->ctrl_mod_reg_offset;
|
|
|
|
+ }
|
|
|
|
+
|
|
priv->emac_base = priv->remap_addr + pdata->ctrl_reg_offset;
|
|
priv->emac_base = priv->remap_addr + pdata->ctrl_reg_offset;
|
|
ndev->base_addr = (unsigned long)priv->remap_addr;
|
|
ndev->base_addr = (unsigned long)priv->remap_addr;
|
|
|
|
|
|
- priv->ctrl_base = priv->remap_addr + pdata->ctrl_mod_reg_offset;
|
|
|
|
-
|
|
|
|
hw_ram_addr = pdata->hw_ram_addr;
|
|
hw_ram_addr = pdata->hw_ram_addr;
|
|
if (!hw_ram_addr)
|
|
if (!hw_ram_addr)
|
|
hw_ram_addr = (u32 __force)res->start + pdata->ctrl_ram_offset;
|
|
hw_ram_addr = (u32 __force)res->start + pdata->ctrl_ram_offset;
|
|
@@ -1980,12 +2021,22 @@ static int davinci_emac_probe(struct platform_device *pdev)
|
|
ndev->ethtool_ops = ðtool_ops;
|
|
ndev->ethtool_ops = ðtool_ops;
|
|
netif_napi_add(ndev, &priv->napi, emac_poll, EMAC_POLL_WEIGHT);
|
|
netif_napi_add(ndev, &priv->napi, emac_poll, EMAC_POLL_WEIGHT);
|
|
|
|
|
|
|
|
+ pm_runtime_enable(&pdev->dev);
|
|
|
|
+ rc = pm_runtime_get_sync(&pdev->dev);
|
|
|
|
+ if (rc < 0) {
|
|
|
|
+ pm_runtime_put_noidle(&pdev->dev);
|
|
|
|
+ dev_err(&pdev->dev, "%s: failed to get_sync(%d)\n",
|
|
|
|
+ __func__, rc);
|
|
|
|
+ goto no_cpdma_chan;
|
|
|
|
+ }
|
|
|
|
+
|
|
/* register the network device */
|
|
/* register the network device */
|
|
SET_NETDEV_DEV(ndev, &pdev->dev);
|
|
SET_NETDEV_DEV(ndev, &pdev->dev);
|
|
rc = register_netdev(ndev);
|
|
rc = register_netdev(ndev);
|
|
if (rc) {
|
|
if (rc) {
|
|
dev_err(&pdev->dev, "error in register_netdev\n");
|
|
dev_err(&pdev->dev, "error in register_netdev\n");
|
|
rc = -ENODEV;
|
|
rc = -ENODEV;
|
|
|
|
+ pm_runtime_put(&pdev->dev);
|
|
goto no_cpdma_chan;
|
|
goto no_cpdma_chan;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1995,9 +2046,7 @@ static int davinci_emac_probe(struct platform_device *pdev)
|
|
"(regs: %p, irq: %d)\n",
|
|
"(regs: %p, irq: %d)\n",
|
|
(void *)priv->emac_base_phys, ndev->irq);
|
|
(void *)priv->emac_base_phys, ndev->irq);
|
|
}
|
|
}
|
|
-
|
|
|
|
- pm_runtime_enable(&pdev->dev);
|
|
|
|
- pm_runtime_resume(&pdev->dev);
|
|
|
|
|
|
+ pm_runtime_put(&pdev->dev);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
@@ -2071,9 +2120,14 @@ static const struct emac_platform_data am3517_emac_data = {
|
|
.hw_ram_addr = 0x01e20000,
|
|
.hw_ram_addr = 0x01e20000,
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+static const struct emac_platform_data dm816_emac_data = {
|
|
|
|
+ .version = EMAC_VERSION_2,
|
|
|
|
+};
|
|
|
|
+
|
|
static const struct of_device_id davinci_emac_of_match[] = {
|
|
static const struct of_device_id davinci_emac_of_match[] = {
|
|
{.compatible = "ti,davinci-dm6467-emac", },
|
|
{.compatible = "ti,davinci-dm6467-emac", },
|
|
{.compatible = "ti,am3517-emac", .data = &am3517_emac_data, },
|
|
{.compatible = "ti,am3517-emac", .data = &am3517_emac_data, },
|
|
|
|
+ {.compatible = "ti,dm816-emac", .data = &dm816_emac_data, },
|
|
{},
|
|
{},
|
|
};
|
|
};
|
|
MODULE_DEVICE_TABLE(of, davinci_emac_of_match);
|
|
MODULE_DEVICE_TABLE(of, davinci_emac_of_match);
|