Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp3211336imu; Sat, 24 Nov 2018 00:11:52 -0800 (PST) X-Google-Smtp-Source: AFSGD/UVU9JDkGYNQZbxPFpJqX6U5rddIGjZrEV1i42uquJOQNRwRcY5nHv5rHo/9fmfCnme1S03 X-Received: by 2002:a17:902:e201:: with SMTP id ce1-v6mr19190380plb.138.1543047112370; Sat, 24 Nov 2018 00:11:52 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1543047112; cv=none; d=google.com; s=arc-20160816; b=ySOLLCRuNj7r5+ZYt5d/k0K+/9NljRGc0z5oTSDuTDUxtsDng/Vb2hp8UwzsFg8hzW yN87bFejzEmUrKEXwip8/KpyeAcrdfIJvUpFq9vYYg3hxSQgtBEdYMfb2Xi7pqStNXrf cOPlaLZ1ncite6RZ2qgpeJqSaqnCx6YjMd7YWWVXBkxLQKok8QBdP7fEtykGqzUYLgTM eHHlQG4hkuh0GbrsNAqFGEKuEgrvW2esN2ON6UPin2GKX3qRyIb93VYCjrVcSxGTxnu4 D6kvKUVLQD9ZIg8TbVqcfBOHqZz1j5MH4BXryurUE1hrPM6b6KS8TaT1yZeXf7KkJ3rR wTKw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:content-transfer-encoding :spamdiagnosticmetadata:spamdiagnosticoutput:content-language :accept-language:in-reply-to:references:message-id:date:thread-index :thread-topic:subject:cc:to:from:dkim-signature; bh=TIgWjMTgqSjsNdi2qwSSYVkSx/qy3rgXVEGq51Ug8zM=; b=oi4P1PAL5+zkN0zUhhKkx1E14ZW7A+zI6kuroo7cdxxKy2oa7vEBoKoUj2cCOT//L/ a00HrALbRyo47j58EytaTnXMw2YS3Wt5VTi8SQ5MqhkLU9u2UqaWc8KQ9eY0do7cM34a Zs6ZxbcK5n2rK9igw8ojFZivcFSfKDpK9VH822p0u6m6qxCfIuvFCVXv1GNocsRJqky9 aVJmw1HuUfeOjyJNPkUqBa7VyYuptcRaw70dmDvaVMloHrL6kp63WFKvhrXNDlH78J7i IuZ8z4dhbxZOh7sTgKPmcijRQno7dB25lBTQB14Tl8ZqM23gOwuC0lhSNWPfv8yB23yg 9a8Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@nxp.com header.s=selector1 header.b=lGkA1k07; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=nxp.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id m142si37241962pfd.171.2018.11.24.00.11.37; Sat, 24 Nov 2018 00:11:52 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@nxp.com header.s=selector1 header.b=lGkA1k07; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=nxp.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2408635AbeKWTSx (ORCPT + 99 others); Fri, 23 Nov 2018 14:18:53 -0500 Received: from mail-eopbgr60041.outbound.protection.outlook.com ([40.107.6.41]:59595 "EHLO EUR04-DB3-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S2408610AbeKWTSv (ORCPT ); Fri, 23 Nov 2018 14:18:51 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nxp.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=TIgWjMTgqSjsNdi2qwSSYVkSx/qy3rgXVEGq51Ug8zM=; b=lGkA1k07eVn+sWYl4Tx87EjIJJRW3KiXzvBavrT7SeIWsz50J4LLafZH1knpkIcdJ17bVU1rToc5HI2OD2q9XqNk2+DxgvfY5yLFvOY7H9mk+++0g5CcONhZdicwmj9G2YD8ISom/OMknRhPFbNH+hojUF57ZWQtM9EJXAXlPU8= Received: from DB7PR04MB4618.eurprd04.prod.outlook.com (52.135.138.152) by DB7PR04MB5483.eurprd04.prod.outlook.com (20.178.105.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1339.26; Fri, 23 Nov 2018 08:35:33 +0000 Received: from DB7PR04MB4618.eurprd04.prod.outlook.com ([fe80::28ab:d6bc:2c00:a54b]) by DB7PR04MB4618.eurprd04.prod.outlook.com ([fe80::28ab:d6bc:2c00:a54b%3]) with mapi id 15.20.1339.029; Fri, 23 Nov 2018 08:35:33 +0000 From: Joakim Zhang To: "linux-can@vger.kernel.org" , "mkl@pengutronix.de" , "robh+dt@kernel.org" CC: "wg@grandegger.com" , "mark.rutland@arm.com" , "devicetree@vger.kernel.org" , "linux-kernel@vger.kernel.org" , dl-linux-imx , Aisheng DONG , Joakim Zhang Subject: [PATCH V6 2/2] can: flexcan: add self wakeup support Thread-Topic: [PATCH V6 2/2] can: flexcan: add self wakeup support Thread-Index: AQHUgwd/2ygbmNueREC7RZQIzROtdw== Date: Fri, 23 Nov 2018 08:35:33 +0000 Message-ID: <20181123083304.3232-3-qiangqing.zhang@nxp.com> References: <20181123083304.3232-1-qiangqing.zhang@nxp.com> In-Reply-To: <20181123083304.3232-1-qiangqing.zhang@nxp.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-mailer: git-send-email 2.17.1 x-clientproxiedby: SG2PR04CA0182.apcprd04.prod.outlook.com (2603:1096:4:14::20) To DB7PR04MB4618.eurprd04.prod.outlook.com (2603:10a6:5:36::24) authentication-results: spf=none (sender IP is ) smtp.mailfrom=qiangqing.zhang@nxp.com; x-ms-exchange-messagesentrepresentingtype: 1 x-originating-ip: [92.121.68.129] x-ms-publictraffictype: Email x-microsoft-exchange-diagnostics: 1;DB7PR04MB5483;6:rRCek+Bq68xUz21quKaYinoUz9AFCiUO5ReKAAIB5ZrfaYqblrdDsyTM5nBwQz8tF7yx5G1FNSz/Vhz4lDwV2z2Qnps/F+Oqy2VkCh7t/QVcyZldcfwhytejj8HreQjdBM7/gYDRA/5EK5uU1ntLGULnyOfcQ8mVK8z1a24eHAEJUpWlE+UlMZxNdjGgRAZcayt2mvjNiEDaMsgzk3wa8xyf4VIV4YKHkPGITR1eWl8Ezd9GQtdtQmBdRqtHoYYNMvouc9kN81igcd0Hh+w7uZgXURGjGlpJAWCUK3LLiZuOBxtYdIntQ8Jstv2QA21IAUrGOi05lhY3MayhmE6Ix1XFJXKGYTIELHlNrQU8OEpJpZIMMwNefCRa4WQfPHVDPdnuITp3d9jBpBwW/Qs+rt4cJx2nbn9/xCL5BuNbUTM/qWWNf9wj62GBDcIlBtApFJylrmBuGgaDWCB5e6MeZg==;5:ymeWTHYEif7TrgXCQwG1HH1NhPj6YsvPXCmre8WwwP45DQRDiSS6N5s6O4W4HgVbfcAhgft++8bvh2PQtONpfJwBGsohIN3ltOp8HGHM+Rfwf5jaiVREUcMrSMXIgv70hssPMN5Nq5JMc3Qq3KK1lQ9UNqRbmp8P5wv0AsrAbuo=;7:nn0l9vX6DH3cKazVaL/KaM2a7cUOGm7yU+2PyyANbs0sVbpoifu9jhx8VEwnMk8UsxoxCLypeb3IsXTLxf6Y0SdiKKfaRYvk3eoq0gkN9IiHKRt5FoUECM+vmWs0J2qMT/nNVSLpp010whNgPqOucw== x-ms-office365-filtering-correlation-id: 9c301159-2e40-4369-5446-08d6511ea1f7 x-ms-office365-filtering-ht: Tenant x-microsoft-antispam: BCL:0;PCL:0;RULEID:(2390098)(7020095)(4652040)(8989299)(5600074)(711020)(4618075)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(2017052603328)(7153060)(7193020);SRVR:DB7PR04MB5483; x-ms-traffictypediagnostic: DB7PR04MB5483: x-microsoft-antispam-prvs: x-ms-exchange-senderadcheck: 1 x-exchange-antispam-report-cfa-test: BCL:0;PCL:0;RULEID:(8211001083)(6040522)(2401047)(8121501046)(5005006)(93006095)(93001095)(10201501046)(3002001)(3231442)(944501410)(52105112)(6055026)(148016)(149066)(150057)(6041310)(20161123562045)(20161123564045)(20161123558120)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123560045)(201708071742011)(7699051)(76991095);SRVR:DB7PR04MB5483;BCL:0;PCL:0;RULEID:;SRVR:DB7PR04MB5483; x-forefront-prvs: 086597191B x-forefront-antispam-report: SFV:NSPM;SFS:(10009020)(376002)(346002)(396003)(136003)(366004)(39860400002)(54534003)(189003)(199004)(25786009)(99286004)(6436002)(8676002)(81156014)(478600001)(305945005)(68736007)(7736002)(11346002)(14454004)(2501003)(86362001)(97736004)(2906002)(2616005)(2900100001)(476003)(486006)(386003)(6486002)(6116002)(5024004)(53936002)(6512007)(3846002)(1076002)(14444005)(106356001)(105586002)(81166006)(50226002)(71190400001)(5660300001)(66066001)(71200400001)(4326008)(8936002)(102836004)(6506007)(446003)(186003)(52116002)(26005)(36756003)(316002)(76176011)(110136005)(54906003)(256004);DIR:OUT;SFP:1101;SCL:1;SRVR:DB7PR04MB5483;H:DB7PR04MB4618.eurprd04.prod.outlook.com;FPR:;SPF:None;LANG:en;PTR:InfoNoRecords;MX:1;A:1; received-spf: None (protection.outlook.com: nxp.com does not designate permitted sender hosts) x-microsoft-antispam-message-info: ymKuLgfsbPjPiBsvwU8VgF4oYayBNS66u+qMDFGPOxtWE6lumVYV+rBfe3cTjCYtiELhiVDgZPQIYl2hTddly3NKEDvsyPy3eT71aD0CkSxPmyvgP/0D2/4qe8n5sE9LO37vtbEQ4UHFY+x84D2toOBrw1CcqpkMBQjBTEr+hOWaTw3YuGg4mmAybaPfJCWK+Ly/XwxrcONyIDMvr5FYMIM87ZJGDsUgD45ERS1TQIWBB40TE6i4t7N8jd1anojPNOdxc5vvgV0UmQmpflwsmyt5/owJdXsu7AxByS4mi4MZMd0ra50OZXtUe8hKMY2BaDNp5aNJR43CtuIYnat23wAd5Cn3sr3cB9cn+ug0aak= spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-Network-Message-Id: 9c301159-2e40-4369-5446-08d6511ea1f7 X-MS-Exchange-CrossTenant-originalarrivaltime: 23 Nov 2018 08:35:33.0525 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB7PR04MB5483 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Aisheng Dong If wakeup is enabled, enter stop mode, else enter disabled mode. Self wake can only work on stop mode. Starting from IMX6, the flexcan stop mode control bits is SoC specific, move it out of IP driver and parse it from devicetree. Signed-off-by: Aisheng Dong Signed-off-by: Joakim Zhang --- ChangeLog: V1->V2: *add a vendor prefix in property (stop-mode -> fsl,stop-mode). V2->V3: *add FLEXCAN_QUIRK_SETUP_STOP_MODE quirk. *rename function. *fix system can't be wakeuped during suspend. V3->V4: *normalize the code following Aisheng Dong's comments. V4->V5: *move enable/disable self wakeup feature into enter/exit_stop_mode() function. V5->V6: *exchange the order of flexcan_enable_wakeup_irq(priv, false) and disable_irq_wake(dev->irq). --- drivers/net/can/flexcan.c | 172 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 163 insertions(+), 9 deletions(-) diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 8e972ef08637..da08a8c113d2 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -19,11 +19,14 @@ #include #include #include +#include +#include #include #include #include #include #include +#include =20 #define DRV_NAME "flexcan" =20 @@ -131,7 +134,8 @@ (FLEXCAN_ESR_ERR_BUS | FLEXCAN_ESR_ERR_STATE) #define FLEXCAN_ESR_ALL_INT \ (FLEXCAN_ESR_TWRN_INT | FLEXCAN_ESR_RWRN_INT | \ - FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT) + FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT | \ + FLEXCAN_ESR_WAK_INT) =20 /* FLEXCAN interrupt flag register (IFLAG) bits */ /* Errata ERR005829 step7: Reserve first valid MB */ @@ -190,6 +194,7 @@ #define FLEXCAN_QUIRK_USE_OFF_TIMESTAMP BIT(5) /* Use timestamp based offl= oading */ #define FLEXCAN_QUIRK_BROKEN_PERR_STATE BIT(6) /* No interrupt for error p= assive */ #define FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN BIT(7) /* default to BE register = access */ +#define FLEXCAN_QUIRK_SETUP_STOP_MODE BIT(8) /* Setup stop mode to suppor= t wakeup */ =20 /* Structure of the message buffer */ struct flexcan_mb { @@ -254,6 +259,14 @@ struct flexcan_devtype_data { u32 quirks; /* quirks needed for different IP cores */ }; =20 +struct flexcan_stop_mode { + struct regmap *gpr; + u8 req_gpr; + u8 req_bit; + u8 ack_gpr; + u8 ack_bit; +}; + struct flexcan_priv { struct can_priv can; struct can_rx_offload offload; @@ -270,6 +283,7 @@ struct flexcan_priv { struct clk *clk_per; const struct flexcan_devtype_data *devtype_data; struct regulator *reg_xceiver; + struct flexcan_stop_mode stm; =20 /* Read and Write APIs */ u32 (*read)(void __iomem *addr); @@ -293,7 +307,8 @@ static const struct flexcan_devtype_data fsl_imx28_devt= ype_data =3D { =20 static const struct flexcan_devtype_data fsl_imx6q_devtype_data =3D { .quirks =3D FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS | - FLEXCAN_QUIRK_USE_OFF_TIMESTAMP | FLEXCAN_QUIRK_BROKEN_PERR_STATE, + FLEXCAN_QUIRK_USE_OFF_TIMESTAMP | FLEXCAN_QUIRK_BROKEN_PERR_STATE | + FLEXCAN_QUIRK_SETUP_STOP_MODE, }; =20 static const struct flexcan_devtype_data fsl_vf610_devtype_data =3D { @@ -353,6 +368,49 @@ static inline void flexcan_write_le(u32 val, void __io= mem *addr) iowrite32(val, addr); } =20 +static void flexcan_enable_wakeup_irq(struct flexcan_priv *priv, bool enab= le) +{ + struct flexcan_regs __iomem *regs =3D priv->regs; + u32 reg_mcr; + + reg_mcr =3D priv->read(®s->mcr); + + if (enable) + reg_mcr |=3D FLEXCAN_MCR_WAK_MSK; + else + reg_mcr &=3D ~FLEXCAN_MCR_WAK_MSK; + + priv->write(reg_mcr, ®s->mcr); +} + +static inline void flexcan_enter_stop_mode(struct flexcan_priv *priv) +{ + struct flexcan_regs __iomem *regs =3D priv->regs; + u32 reg_mcr; + + reg_mcr =3D priv->read(®s->mcr); + reg_mcr |=3D FLEXCAN_MCR_SLF_WAK; + priv->write(reg_mcr, ®s->mcr); + + /* enable stop request */ + regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr, + 1 << priv->stm.req_bit, 1 << priv->stm.req_bit); +} + +static inline void flexcan_exit_stop_mode(struct flexcan_priv *priv) +{ + struct flexcan_regs __iomem *regs =3D priv->regs; + u32 reg_mcr; + + /* remove stop request */ + regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr, + 1 << priv->stm.req_bit, 0); + + reg_mcr =3D priv->read(®s->mcr); + reg_mcr &=3D ~FLEXCAN_MCR_SLF_WAK; + priv->write(reg_mcr, ®s->mcr); +} + static inline void flexcan_error_irq_enable(const struct flexcan_priv *pri= v) { struct flexcan_regs __iomem *regs =3D priv->regs; @@ -1244,6 +1302,57 @@ static void unregister_flexcandev(struct net_device = *dev) unregister_candev(dev); } =20 +static int flexcan_setup_stop_mode(struct platform_device *pdev) +{ + struct net_device *dev =3D platform_get_drvdata(pdev); + struct device_node *np =3D pdev->dev.of_node; + struct device_node *gpr_np; + struct flexcan_priv *priv; + phandle phandle; + u32 out_val[5]; + int ret; + + if (!np) + return -EINVAL; + + /* stop mode property format is: + * <&gpr req_gpr req_bit ack_gpr ack_bit>. + */ + ret =3D of_property_read_u32_array(np, "fsl,stop-mode", out_val, 5); + if (ret) { + dev_dbg(&pdev->dev, "no stop-mode property\n"); + return ret; + } + phandle =3D *out_val; + + gpr_np =3D of_find_node_by_phandle(phandle); + if (!gpr_np) { + dev_dbg(&pdev->dev, "could not find gpr node by phandle\n"); + return PTR_ERR(gpr_np); + } + + priv =3D netdev_priv(dev); + priv->stm.gpr =3D syscon_node_to_regmap(gpr_np); + of_node_put(gpr_np); + if (IS_ERR(priv->stm.gpr)) { + dev_dbg(&pdev->dev, "could not find gpr regmap\n"); + return PTR_ERR(priv->stm.gpr); + } + + priv->stm.req_gpr =3D out_val[1]; + priv->stm.req_bit =3D out_val[2]; + priv->stm.ack_gpr =3D out_val[3]; + priv->stm.ack_bit =3D out_val[4]; + + dev_dbg(&pdev->dev, "gpr %s req_gpr 0x%x req_bit %u ack_gpr 0x%x ack_bit = %u\n", + gpr_np->full_name, priv->stm.req_gpr, priv->stm.req_bit, priv->stm.ack_g= pr, + priv->stm.ack_bit); + + device_set_wakeup_capable(&pdev->dev, true); + + return 0; +} + static const struct of_device_id flexcan_of_match[] =3D { { .compatible =3D "fsl,imx6q-flexcan", .data =3D &fsl_imx6q_devtype_data,= }, { .compatible =3D "fsl,imx28-flexcan", .data =3D &fsl_imx28_devtype_data,= }, @@ -1396,6 +1505,12 @@ static int flexcan_probe(struct platform_device *pde= v) =20 devm_can_led_init(dev); =20 + if (priv->devtype_data->quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE) { + err =3D flexcan_setup_stop_mode(pdev); + if (err) + dev_dbg(&pdev->dev, "failed to setup stop-mode\n"); + } + dev_info(&pdev->dev, "device registered (reg_base=3D%p, irq=3D%d)\n", priv->regs, dev->irq); =20 @@ -1426,9 +1541,17 @@ static int __maybe_unused flexcan_suspend(struct dev= ice *device) int err; =20 if (netif_running(dev)) { - err =3D flexcan_chip_disable(priv); - if (err) - return err; + /* if wakeup is enabled, enter stop mode + * else enter disabled mode. + */ + if (device_may_wakeup(device)) { + enable_irq_wake(dev->irq); + flexcan_enter_stop_mode(priv); + } else { + err =3D flexcan_chip_disable(priv); + if (err) + return err; + } netif_stop_queue(dev); netif_device_detach(dev); } @@ -1447,14 +1570,45 @@ static int __maybe_unused flexcan_resume(struct dev= ice *device) if (netif_running(dev)) { netif_device_attach(dev); netif_start_queue(dev); - err =3D flexcan_chip_enable(priv); - if (err) - return err; + if (device_may_wakeup(device)) { + disable_irq_wake(dev->irq); + } else { + err =3D flexcan_chip_enable(priv); + if (err) + return err; + } } return 0; } =20 -static SIMPLE_DEV_PM_OPS(flexcan_pm_ops, flexcan_suspend, flexcan_resume); +static int __maybe_unused flexcan_noirq_suspend(struct device *device) +{ + struct net_device *dev =3D dev_get_drvdata(device); + struct flexcan_priv *priv =3D netdev_priv(dev); + + if (netif_running(dev) && device_may_wakeup(device)) + flexcan_enable_wakeup_irq(priv, true); + + return 0; +} + +static int __maybe_unused flexcan_noirq_resume(struct device *device) +{ + struct net_device *dev =3D dev_get_drvdata(device); + struct flexcan_priv *priv =3D netdev_priv(dev); + + if (netif_running(dev) && device_may_wakeup(device)) { + flexcan_enable_wakeup_irq(priv, false); + flexcan_exit_stop_mode(priv); + } + + return 0; +} + +static const struct dev_pm_ops flexcan_pm_ops =3D { + SET_SYSTEM_SLEEP_PM_OPS(flexcan_suspend, flexcan_resume) + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(flexcan_noirq_suspend, flexcan_noirq_resume= ) +}; =20 static struct platform_driver flexcan_driver =3D { .driver =3D { --=20 2.17.1