#include <linux/regulator/consumer.h>
#include <linux/if_vlan.h>
#include <linux/pm_runtime.h>
+#include <linux/pm_qos.h>
#include <linux/version.h>
#include <asm/cacheflush.h>
* frames not being transmitted until there is a 0-to-1 transition on
* ENET_TDAR[TDAR].
*/
-#define FEC_QUIRK_ERR006358 (1 << 7)
+#define FEC_QUIRK_ERR006358 (1 << 8)
+/*
+ * 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 << 9)
static struct platform_device_id fec_devtype[] = {
{
.name = "imx6q-fec",
.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_VLAN | FEC_QUIRK_ERR006358 |
+ FEC_QUIRK_BUG_WAITMODE,
}, {
.name = "mvf600-fec",
.driver_data = FEC_QUIRK_ENET_MAC,
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;
pm_runtime_get_sync(ndev->dev.parent);
+ if (id_entry->driver_data & FEC_QUIRK_BUG_WAITMODE)
+ pm_qos_add_request(&ndev->pm_qos_req,
+ PM_QOS_CPU_DMA_LATENCY,
+ 0);
+ else
+ pm_qos_add_request(&ndev->pm_qos_req,
+ PM_QOS_CPU_DMA_LATENCY,
+ PM_QOS_DEFAULT_VALUE);
fec_enet_clk_enable(ndev, true);
fec_enet_clk_enable(ndev, false);
+ pm_qos_remove_request(&ndev->pm_qos_req);
pm_runtime_put_sync_suspend(ndev->dev.parent);
fec_enet_free_buffers(ndev);