#include <linux/clocksource.h>
#include <linux/net_tstamp.h>
+#include <linux/pm_qos.h>
#include <linux/ptp_clock_kernel.h>
#include <linux/timecounter.h>
#define FEC_QUIRK_HAS_COALESCE (1 << 13)
/* Interrupt doesn't wake CPU from deep idle */
#define FEC_QUIRK_ERR006687 (1 << 14)
+/*
+ * i.MX6Q/DL ENET cannot wake up system in wait mode because ENET tx & rx
+ * interrupt signal don't connect to GPC. So use pm qos to avoid cpu enter
+ * to wait mode.
+ */
+#define FEC_QUIRK_BUG_WAITMODE (1 << 15)
struct bufdesc_prop {
int qid;
int hwts_tx_en;
struct delayed_work time_keep;
struct regulator *reg_phy;
+ struct pm_qos_request pm_qos_req;
unsigned int tx_align;
unsigned int rx_align;
.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR006358 |
- FEC_QUIRK_HAS_RACC,
+ FEC_QUIRK_HAS_RACC | FEC_QUIRK_BUG_WAITMODE,
}, {
.name = "mvf600-fec",
.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_RACC,
return 0;
}
+static inline bool fec_enet_irq_workaround(struct fec_enet_private *fep)
+{
+ struct device_node *np = fep->pdev->dev.of_node;
+ struct device_node *intr_node;
+
+ intr_node = of_parse_phandle(np, "interrupts-extended", 0);
+ if (intr_node && !strcmp(intr_node->name, "gpio")) {
+ /*
+ * If the interrupt controller is a GPIO node, it must have
+ * applied the workaround for WAIT mode bug.
+ */
+ return true;
+ }
+
+ return false;
+}
+
static int
fec_enet_open(struct net_device *ndev)
{
struct fec_enet_private *fep = netdev_priv(ndev);
+ const struct platform_device_id *id_entry =
+ platform_get_device_id(fep->pdev);
int ret;
ret = pm_runtime_get_sync(&fep->pdev->dev);
phy_start(ndev->phydev);
netif_tx_start_all_queues(ndev);
+ if ((id_entry->driver_data & FEC_QUIRK_BUG_WAITMODE) &&
+ !fec_enet_irq_workaround(fep))
+ pm_qos_add_request(&fep->pm_qos_req,
+ PM_QOS_CPU_DMA_LATENCY,
+ 0);
+ else
+ pm_qos_add_request(&fep->pm_qos_req,
+ PM_QOS_CPU_DMA_LATENCY,
+ PM_QOS_DEFAULT_VALUE);
+
device_set_wakeup_enable(&ndev->dev, fep->wol_flag &
FEC_WOL_FLAG_ENABLE);